欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis搶單預(yù)熱的實(shí)現(xiàn)示例

 更新時(shí)間:2023年11月22日 11:40:09   作者:zhizhiqiuya  
本文主要介紹了Redis搶單預(yù)熱的實(shí)現(xiàn)示例,以應(yīng)對(duì)搶單活動(dòng)帶來的高并發(fā)訪問壓力,具有一定的參考價(jià)值,感興趣的可以了解一下

前言

在當(dāng)今的互聯(lián)網(wǎng)時(shí)代,搶單活動(dòng)已經(jīng)成為了電商平臺(tái)、外賣平臺(tái)等各種電子商務(wù)平臺(tái)中常見的營銷手段。通過搶單活動(dòng),商家可以吸引大量用戶參與,從而提高銷量和知名度。然而,搶單活動(dòng)所帶來的高并發(fā)請(qǐng)求往往會(huì)給系統(tǒng)帶來巨大的壓力,如何在搶單活動(dòng)開始前進(jìn)行預(yù)熱,以確保系統(tǒng)能夠穩(wěn)定運(yùn)行,成為了技術(shù)人員需要解決的重要問題。

在這篇博客中,我們將深入探討如何利用Redis技術(shù)來進(jìn)行搶單預(yù)熱,以應(yīng)對(duì)搶單活動(dòng)帶來的高并發(fā)訪問壓力。我們將介紹Redis的基本概念和特點(diǎn),以及如何利用Redis來進(jìn)行緩存預(yù)熱、數(shù)據(jù)預(yù)加載等操作,從而提高系統(tǒng)的并發(fā)處理能力和穩(wěn)定性。同時(shí),我們也將分享一些實(shí)際案例和經(jīng)驗(yàn),幫助讀者更好地理解和應(yīng)用Redis技術(shù)解決搶單預(yù)熱的挑戰(zhàn)。

通過本文的學(xué)習(xí),讀者將能夠深入了解搶單預(yù)熱的必要性和原理,掌握利用Redis進(jìn)行搶單預(yù)熱的具體方法和技巧,從而為自己的系統(tǒng)應(yīng)對(duì)搶單活動(dòng)帶來的高并發(fā)訪問壓力提供有效的解決方案。讓我們一起深入探討Redis在搶單預(yù)熱中的應(yīng)用吧!

一、前期準(zhǔn)備

1、新建項(xiàng)目,結(jié)構(gòu)如下

 2、添加依賴

<dependencies>
        <!-- 放在最前面依賴,依據(jù)依賴的最短路徑原則,
             將不在使用spring-data中的slf4j,否則
             會(huì)引發(fā)沖突-->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.3.8</version>
        </dependency>

        <!-- spring data框架,提供了對(duì)redis的整合支持,
             內(nèi)部支持lettuce以及Jedis客戶端-->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>2.5.6</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.29</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.29</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.29</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.32</version>
        </dependency>

        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>6.2.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.2</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
    </dependencies>

這個(gè)Maven項(xiàng)目中包含了多個(gè)依賴,以下是每個(gè)依賴的作用:

logback-classic: 這是logback日志框架的經(jīng)典模塊,用于在應(yīng)用程序中進(jìn)行日志記錄和管理。

spring-data-redis: 提供了Spring Data框架對(duì)Redis的整合支持,包括對(duì)lettuce和Jedis客戶端的支持,可以方便地使用Redis進(jìn)行數(shù)據(jù)操作。

javax.servlet-api: 這是Java Servlet API的依賴,提供了對(duì)Servlet的支持,通常在Java Web應(yīng)用中使用。

spring-webmvc: Spring框架的Web MVC模塊,提供了基于MVC架構(gòu)的Web應(yīng)用程序開發(fā)支持。

spring-jdbc: Spring框架的JDBC模塊,提供了對(duì)JDBC的封裝和支持,用于在Spring應(yīng)用中進(jìn)行數(shù)據(jù)庫操作。

spring-tx: Spring框架的事務(wù)管理模塊,提供了聲明式事務(wù)管理的支持。

druid: 阿里巴巴開源的數(shù)據(jù)庫連接池,在應(yīng)用中用于管理數(shù)據(jù)庫連接。

mysql-connector-java: MySQL數(shù)據(jù)庫的JDBC驅(qū)動(dòng),用于連接MySQL數(shù)據(jù)庫。

lettuce-core: Lettuce是一個(gè)高性能的開源Java Redis客戶端,用于與Redis進(jìn)行交互。

lombok: Lombok是一個(gè)Java庫,可以通過注解的方式來簡化Java代碼的編寫,提高開發(fā)效率。

junit: JUnit是一個(gè)Java單元測試框架,用于編寫和運(yùn)行自動(dòng)化的單元測試。

jackson-databind: Jackson是一個(gè)流行的Java JSON處理庫,jackson-databind模塊提供了數(shù)據(jù)綁定功能,用于將Java對(duì)象和JSON數(shù)據(jù)進(jìn)行相互轉(zhuǎn)換。

mybatis: MyBatis是一個(gè)持久層框架,用于在Java應(yīng)用中進(jìn)行數(shù)據(jù)庫操作。

mybatis-spring: MyBatis與Spring框架的整合模塊,提供了MyBatis和Spring框架的無縫集成支持。

這些依賴項(xiàng)涵蓋了日志記錄、Web開發(fā)、數(shù)據(jù)庫操作、緩存操作、測試等多個(gè)方面,可以滿足一個(gè)典型的Java應(yīng)用程序的開發(fā)需求。

二、編寫 dao

由于代碼量太多了,就不一一講解了,本次案例只是講重要的怎么預(yù)熱和減庫存。 

1、GoodsDao

public interface GoodsDao {

    /**
     * 查詢參與活動(dòng)的商品
     * @return
     */
    List<Goods> listProduct();

    /**
     * 減庫存
     * @param id
     * @return
     */
    void decrStock(int id);
}

首先要有一個(gè)查詢庫存的方法和一個(gè)刪減庫存的方法。 

三、編寫 service

1、OrderService

public interface OrderService {
    /**
     * 下單
     * @param id
     */
    void placeOrder(int id);
}

 當(dāng)庫存放生改變時(shí),我們需要為這寫下單的用戶添加訂單記錄。

2、GoodsService

public interface GoodsService {

    /**
     * 扣減庫存
     * @param id
     */
    void decrStock(int id);
}

當(dāng)下單成功后,需要扣減數(shù)據(jù)庫的庫存數(shù)量。

3、GoodsServiceImpl

@Service
@Slf4j
@RequiredArgsConstructor
@Transactional(rollbackFor = RuntimeException.class)
public class GoodsServiceImpl implements GoodsService {

    private final GoodsDao goodsDao;

    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 緩存預(yù)熱
     */
    @PostConstruct
    public void initProductCache() {
        goodsDao.listProduct().forEach(goods -> {
            //將商品數(shù)量加入redis緩存
            String key = GoodsEnum.PREFIX.value() + goods.getId();
            redisTemplate.opsForValue().set(key, goods.getStock(), Duration.ofMinutes(60));
        });
    }

    @Override
    public void decrStock(int id) {
        goodsDao.decrStock(id);
    }
}

這段代碼是一個(gè)名為GoodsServiceImpl的服務(wù)類,使用了Lombok的@RequiredArgsConstructor注解來自動(dòng)生成構(gòu)造函數(shù),并且使用了Slf4j來實(shí)現(xiàn)日志記錄。同時(shí),@Service注解表明這是一個(gè)Spring的服務(wù)類,@Transactional注解表明這個(gè)類中的方法將進(jìn)行事務(wù)管理,并且在遇到RuntimeException時(shí)進(jìn)行回滾。

這個(gè)類中有兩個(gè)成員變量:GoodsDao和RedisTemplate。GoodsDao是一個(gè)數(shù)據(jù)訪問對(duì)象,用于對(duì)商品數(shù)據(jù)進(jìn)行持久化操作;而RedisTemplate是Spring提供的用于操作Redis的模板類。

在這個(gè)類中,有一個(gè)@PostConstruct注解的方法initProductCache(),它在類實(shí)例化后會(huì)被自動(dòng)調(diào)用。這個(gè)方法通過goodsDao.listProduct()獲取所有商品,并將它們的庫存數(shù)量加入到Redis緩存中,以實(shí)現(xiàn)商品的緩存預(yù)熱。對(duì)于每個(gè)商品,它會(huì)將商品的id作為key,庫存數(shù)量作為value存入Redis,并設(shè)置了緩存的有效期為60分鐘。

另外,這個(gè)類還實(shí)現(xiàn)了GoodsService接口,其中包含了decrStock(int id)方法,用于減少商品庫存。在這個(gè)方法中,它調(diào)用了goodsDao.decrStock(id)來實(shí)現(xiàn)對(duì)商品庫存的減少操作。

總的來說,這個(gè)類主要負(fù)責(zé)商品庫存的管理,通過緩存預(yù)熱來提高系統(tǒng)性能,并且在減少商品庫存時(shí)進(jìn)行事務(wù)管理。

4、OrderServiceImpl

@Service
@Slf4j
@RequiredArgsConstructor
@Transactional
public class OrderServiceImpl implements OrderService {

    private final RedisTemplate<String, Object> redisTemplate;

    private final OrderDao orderDao;

    private final GoodsDao goodsDao;

    /**
     * 下單
     * @param id
     */
    @Override
    public void placeOrder(int id) {
        //扣減庫存
        decrCacheStock(id);
        //生成訂單
        createOrder(id);
        //同步數(shù)據(jù)庫的庫存
        goodsDao.decrStock(id);
    }

    /**
     * 在緩存中扣減庫存
     * @param id
     */
    private void decrCacheStock(int id) {
        //扣減庫存(原子減),并返回剩余庫存量
        long stock = redisTemplate.opsForValue().decrement(GoodsEnum.PREFIX.value() + id);
        //如果redis中庫存為0,則拋出異常告訴用戶已經(jīng)售罄
        if(stock < 0) {
            //在并發(fā)時(shí)redis扣減后的庫存為負(fù)數(shù),因此要將redis自增回來
            redisTemplate.opsForValue().increment(GoodsEnum.PREFIX.value() + id);
            throw new OrderException(ErrorMessageEnum.SELL_OUT);
        }
    }

    /**
     * 生成訂單
     * @param gid
     */
    private Order createOrder(int gid) {
        try {
            Order order = new Order();
            //用戶ID
            order.setUserId(1);
            //商品ID
            order.setGoodsId(gid);
            //0表示未支付
            order.setStatus(0);
            orderDao.save(order);
            return order;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }
}

 這段代碼是一個(gè)名為OrderServiceImpl的服務(wù)類,同樣使用了Lombok的@RequiredArgsConstructor注解來自動(dòng)生成構(gòu)造函數(shù),并且使用了@Slf4j來實(shí)現(xiàn)日志記錄。同時(shí),@Service注解表明這是一個(gè)Spring的服務(wù)類,@Transactional注解表明這個(gè)類中的方法將進(jìn)行事務(wù)管理。

這個(gè)類中有三個(gè)成員變量:RedisTemplate用于操作Redis緩存,OrderDao用于對(duì)訂單數(shù)據(jù)進(jìn)行持久化操作,GoodsDao用于對(duì)商品數(shù)據(jù)進(jìn)行持久化操作。

在這個(gè)類中,有一個(gè)placeOrder(int id)方法,用于處理下單操作。在這個(gè)方法中,首先調(diào)用了decrCacheStock(int id)方法來扣減商品的庫存,然后調(diào)用了createOrder(int id)方法來生成訂單,最后調(diào)用了goodsDao.decrStock(id)方法來同步數(shù)據(jù)庫中的庫存信息。

在decrCacheStock(int id)方法中,它使用了RedisTemplate來實(shí)現(xiàn)對(duì)Redis緩存中商品庫存的扣減操作,并且通過判斷庫存是否小于0來判斷商品是否售罄,如果售罄則拋出OrderException異常。

在createOrder(int gid)方法中,它創(chuàng)建了一個(gè)訂單對(duì)象,并將訂單信息存入數(shù)據(jù)庫中。如果在存入數(shù)據(jù)庫時(shí)出現(xiàn)異常,它會(huì)記錄錯(cuò)誤日志并拋出RuntimeException異常。

總的來說,這個(gè)類主要負(fù)責(zé)處理訂單的生成和庫存的扣減操作,通過調(diào)用RedisTemplate來實(shí)現(xiàn)對(duì)Redis緩存的操作,并且在數(shù)據(jù)庫操作時(shí)進(jìn)行事務(wù)管理。

四、編寫controller

@RestController
@RequiredArgsConstructor
public class OrderController extends BaseController{

    private final OrderService orderService;

    @PostMapping("/seckill")
    public ResultVO placeOrder(Integer gid) {
        orderService.placeOrder(2);
        return success();
    }
}

這段代碼是一個(gè)名為OrderController的控制器類,使用了Lombok的@RequiredArgsConstructor注解來自動(dòng)生成構(gòu)造函數(shù),并且繼承了BaseController。同時(shí),@RestController注解表明這是一個(gè)Spring的RESTful控制器類。

在這個(gè)類中,有一個(gè)成員變量OrderService,用于處理訂單相關(guān)的業(yè)務(wù)邏輯。在控制器中,有一個(gè)@PostMapping注解的方法placeOrder(Integer gid),用于處理秒殺下單的請(qǐng)求。在這個(gè)方法中,它調(diào)用了orderService.placeOrder(2)來處理下單操作,并且返回了一個(gè)ResultVO對(duì)象,通過success()方法來表示操作成功。

總的來說,這個(gè)控制器類主要用于處理秒殺下單的請(qǐng)求,通過調(diào)用OrderService來實(shí)現(xiàn)下單操作,并返回相應(yīng)的結(jié)果。

五、使用jmeter測試

官網(wǎng)網(wǎng)址:Apache JMeter - Apache JMeter™

去官網(wǎng)下載下來,我們用 jmeter 來測試我們的controller。

 1、jmeter有什么用

JMeter是一個(gè)用于進(jìn)行性能測試的開源工具,它最初是為測試Web應(yīng)用程序而設(shè)計(jì)的,但后來擴(kuò)展到其他測試領(lǐng)域。JMeter的主要用途包括:

  • 性能測試:JMeter可以模擬多個(gè)并發(fā)用戶對(duì)目標(biāo)系統(tǒng)(如Web服務(wù)器、數(shù)據(jù)庫、FTP服務(wù)器等)發(fā)起請(qǐng)求,以評(píng)估系統(tǒng)的性能和穩(wěn)定性。它可以測量系統(tǒng)在不同負(fù)載下的響應(yīng)時(shí)間、吞吐量和并發(fā)用戶數(shù)等指標(biāo),幫助開發(fā)人員和測試人員發(fā)現(xiàn)系統(tǒng)性能方面的問題。

  • 負(fù)載測試:通過模擬大量用戶請(qǐng)求,JMeter可以測試系統(tǒng)在高負(fù)載情況下的表現(xiàn),評(píng)估系統(tǒng)的承載能力和性能瓶頸,以便確定系統(tǒng)是否能夠滿足預(yù)期的用戶需求。負(fù)載測試也可以用于驗(yàn)證系統(tǒng)的可伸縮性和穩(wěn)定性。

  • 壓力測試:JMeter可以模擬系統(tǒng)在正?;虍惓X?fù)載下的表現(xiàn),以便評(píng)估系統(tǒng)在不同壓力下的穩(wěn)定性和可靠性。通過壓力測試,可以發(fā)現(xiàn)系統(tǒng)在極端情況下可能出現(xiàn)的問題,如內(nèi)存泄漏、資源競爭等。

  • 功能測試:除了性能測試,JMeter也可以用于進(jìn)行功能測試,例如測試網(wǎng)站的登錄、注冊、搜索等功能,以及測試API的響應(yīng)等。

總的來說,JMeter是一個(gè)功能強(qiáng)大的測試工具,可以幫助開發(fā)人員和測試人員進(jìn)行性能、負(fù)載、壓力和功能測試,以確保系統(tǒng)能夠穩(wěn)定、高效地運(yùn)行。

2、測試

1)打開 jmeter ,bin目錄下雙擊ApacheJMeter.jar 運(yùn)行

運(yùn)行:

 2)添加線程組

3)添加HTTP請(qǐng)求

4)添加匯總報(bào)告

5)填寫信息

 添加循環(huán)數(shù)量,我們的庫存中有100個(gè)庫存,我們執(zhí)行150次,看會(huì)不會(huì)出現(xiàn)超賣的情況。還是售完了直接就拋異常。

填寫 HTTP 協(xié)議

請(qǐng)求路徑不要寫錯(cuò)了,還有就是請(qǐng)求的方式是什么就選擇什么。

6)測試結(jié)果

當(dāng)運(yùn)行測試后,售完100個(gè)數(shù)量之后并沒有出現(xiàn)超賣的現(xiàn)象,證明我們的代碼就沒有寫錯(cuò),并且在售完之后直接提示用戶商品已售完。

六、gitee 案例

地址:ch02 · qiuqiu/Redis-study - 碼云 - 開源中國 (gitee.com)

到此這篇關(guān)于Redis搶單預(yù)熱的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Redis搶單預(yù)熱內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis 限制內(nèi)存使用大小的實(shí)現(xiàn)

    redis 限制內(nèi)存使用大小的實(shí)現(xiàn)

    這篇文章主要介紹了redis 限制內(nèi)存使用大小的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • 解讀緩存db redis local的取舍之道

    解讀緩存db redis local的取舍之道

    這篇文章主要介紹了解讀緩存db redis local的取舍之道,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Redis 設(shè)置密碼無效問題解決

    Redis 設(shè)置密碼無效問題解決

    本文主要介紹了Redis 設(shè)置密碼無效問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • windows上修改redis端口號(hào)的操作步驟

    windows上修改redis端口號(hào)的操作步驟

    redis是一個(gè)開源的內(nèi)存數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),常用做數(shù)據(jù)庫、緩存和消息代理,默認(rèn)的端口號(hào)為6379,那么如何在windows上修改redis端口號(hào),接下來本文給大家詳細(xì)介紹了windows上修改redis端口號(hào)的操作方法,需要的朋友可以參考下
    2024-02-02
  • redis批量遷移key的實(shí)例

    redis批量遷移key的實(shí)例

    我們知道m(xù)igrate 命令可以遷移redis的多個(gè)key,但是如果redis的key有非常多,就不好解決了,本文主要介紹了redis批量遷移key的實(shí)例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04
  • redis鍵空間通知使用實(shí)現(xiàn)

    redis鍵空間通知使用實(shí)現(xiàn)

    這篇文章主要介紹了redis鍵空間通知使用實(shí)現(xiàn)
    2021-08-08
  • Redis分布式鎖如何自動(dòng)續(xù)期的實(shí)現(xiàn)

    Redis分布式鎖如何自動(dòng)續(xù)期的實(shí)現(xiàn)

    本文主要介紹了Redis分布式鎖如何自動(dòng)續(xù)期的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • redis快速部署為docker容器的方法實(shí)現(xiàn)

    redis快速部署為docker容器的方法實(shí)現(xiàn)

    部署 Redis 作為 Docker 容器是一種快速、靈活且可重復(fù)使用的方式,特別適合開發(fā)、測試和部署環(huán)境,本文主要介紹了redis快速部署為docker容器的方法實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • Redis migrate數(shù)據(jù)遷移工具的使用教程

    Redis migrate數(shù)據(jù)遷移工具的使用教程

    這篇文章主要給大家介紹了關(guān)于Redis migrate數(shù)據(jù)遷移工具的使用教程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Redis如何一鍵部署腳本

    Redis如何一鍵部署腳本

    這篇文章主要介紹了Redis如何一鍵部署腳本,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評(píng)論