Redis實戰(9)-有序集合SortedSet實戰之再談遊戲充值排行榜(處理歷史與異常充值記錄)

概述:本系列博文所涉及的相關內容來源於debug親自錄製的實戰課程:緩存中間件Redis技術入門與應用場景實戰(SpringBoot2.x + 搶紅包系統設計與實戰),感興趣的小夥伴可以點擊自行前往學習(畢竟以視頻的形式來掌握技術 會更快!) ,文章所屬專欄:緩存中間件Redis技術入門與實戰

摘要:每當我們談起緩存中間件Redis的應用場景時,我們一般都會根據其數據結構聯想到對應的應用場景,有序集合SortedSet也不例外,“排行榜”一直都是與其緊密掛鉤、不得不談的其中一種實戰場景!本文我們將繼續再談“遊戲充值排行榜”,介紹如何去處理歷史已經存在的充值記錄 或者 在將充值記錄塞入緩存Cache失敗時如何開啓後續的補償處理措施!

內容:在上篇文章中,我們已經給各位小夥伴介紹瞭如何基於Spring Boot2.0 + 緩存Redis的SortedSet以實際的代碼實戰一種典型的業務場景“遊戲充值排行榜”,在文中我們介紹了這一業務場景兩大典型的核心功能模塊,即“用戶充值”、“獲取充值排行榜”,各位小夥伴可以自行前往回顧!

然而,這世間本就沒有十全十美之物,“遊戲充值排行榜”這一業務場景也不例外,雖然我們基本上已經實現了該業務場景幾乎所有的功能模塊,但是我們卻忽略了其他兩種情況:

A.如果“充值排行榜”這一功能模塊是增量式的需求,那麼上線時如何去處理歷史的用戶充值記錄呢?你總不能說我們的“充值排行榜”對於以往充值的用戶記錄不生效吧?(那樣豈不令人笑掉大牙!)

B.雖然我們的代碼看似完美,但是要知道Bug是無處不在的,這些Bug有的是能一眼被洞穿的,也有的是後知後覺的,“用戶充值的過程”便是如此,如果用戶充值後插入數據庫DB成功、但是插入緩存Cache失敗(DB事務不回滾的前提),那毫無疑問,最終得出來的“充值排行榜”一定是不準確的(因爲我們是直接從緩存Redis中獲取的)

帶着這兩大問題,我們給大家提供了一種並非十全十美的,但是卻能保證“最終一致性”的充值排行榜的解決方案,那就是萬能的定時任務調度

既然是定時任務調度,那麼這個定時任務是做啥的呢?沒錯,它要完成的任務就是開啓一個定時時鐘,基於數據庫DB中的“用戶充值記錄表”,藉助數據庫提供的Order By、Group By等查詢得出目前爲止所有有效用戶的“充值排行榜”,下面我們以實際的代碼進行實戰。

(1)直接建立一個定時任務調度類PhoneFareScheduler,並開發相應的方法實現具體的定時任務邏輯,其完整源代碼如下所示:

/**補償機制:手機號碼充值排行榜
 * @Author:debug (SteadyJack)
 * @Link: weixin-> debug0868 qq-> 1948831260**/
@Component
public class PhoneFareScheduler {
    private static final Logger log= LoggerFactory.getLogger(PhoneFareScheduler.class);
    @Autowired
    private PhoneFareMapper phoneFareMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    //時間頻度設定爲30min,當然啦,具體的設定要根據實際情況而定
    @Scheduled(cron = "0 0/30 * * * ?")
    public void sortFareScheduler(){
        log.info("--補償性手機號碼充值排行榜-定時任務");
        this.cacheSortResult();
    }
    @Async("threadPoolTaskExecutor")
    private void cacheSortResult(){
        try {
            ZSetOperations<String,FareDto> zSetOperations=redisTemplate.opsForZSet();
            List<PhoneFare> list=phoneFareMapper.getAllSortFares();
            if (list!=null && !list.isEmpty()){
                redisTemplate.delete(Constant.RedisSortedSetKey2);
                list.forEach(fare -> {
                    FareDto dto=new FareDto(fare.getPhone());
                    zSetOperations.add(Constant.RedisSortedSetKey2,dto,fare.getFare().doubleValue());
                });
            }
        }catch (Exception e){
            log.error("--補償性手機號碼充值排行榜-定時任務-發生異常:",e.fillInStackTrace());
        }
    }
}

值得一提的是,在該定時任務調度中我們設定的時間頻率爲 每30min進行執行一次任務,實現“充值排行榜”的大洗盤!也就是說,如果前端“排行榜”頁面數據出現差錯,那麼其恢復正確的等待時間是30min(因爲我們的定時任務就是前往數據庫DB,查詢獲取得到排行榜,當然啦,其前提是保證DB中的數據是正確無誤的!)

(2)其中,phoneFareMapper.getAllSortFares() 的作用就是前往數據庫Mysql,通過Group By、Order By和SUM等查詢得到排行榜,其完整的動態SQL如下所示:

  <!--基於數據庫的補償排名機制-->
  <select id="getAllSortFares" resultType="com.boot.debug.redis.model.entity.PhoneFare">
    SELECT
        phone,
        SUM(fare) AS fare
    FROM
        phone_fare
    GROUP BY
        phone
    ORDER BY
        fare DESC
  </select>

除此之外,@Async("threadPoolTaskExecutor") 的作用便是採用“線程池-多線程的方式異步執行定時任務”,故而我們需要作一個全局的Config,用於配置線程池-多線程的相關信息:  

/**線程池-多線程配置
 * @Author:debug (SteadyJack)
 * @Link: weixin-> debug0868 qq-> 1948831260**/
public class ThreadConfig {
    @Bean("threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(8);
        executor.setKeepAliveSeconds(10);
        executor.setQueueCapacity(8);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}

至此,我們已經擼完了“遊戲充值排行榜”這一完整業務的“補償機制”功能代碼了,在測試之前,我們先“偷偷”在數據庫表phone_fare中新增幾條充值記錄,代表“以前存在的歷史充值記錄”或者“插入DB成功,但插入緩存失敗的充值記錄”,如下圖所示:

最後我們基於Postman測試一波吧,下面一張圖足以說明一切了:

好了,本篇文章我們就介紹到這裏了,建議各位小夥伴一定要照着文章提供的樣例代碼擼一擼,只有擼過才能知道這玩意是咋用的,否則就成了“空談者”!對Redis相關技術棧以及實際應用場景實戰感興趣的小夥伴可以咱們51cto學院 debug親自錄製的課程進行學習:緩存中間件Redis技術入門與應用場景實戰(SpringBoot2.x + 搶紅包系統設計與實戰)

補充:

1、本文涉及到的相關的源代碼可以到此地址,check出來進行查看學習:https://gitee.com/steadyjack/SpringBootRedis

2、目前debug已將本文所涉及的內容整理錄製成視頻教程,感興趣的小夥伴可以前往觀看學習:https://edu.51cto.com/course/20384.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章