Redis實現(xiàn)未讀消息計數(shù)的示例代碼
一、業(yè)務(wù)場景說明
在合伙人系統(tǒng)的產(chǎn)品分配流程中,存在兩種分配模式,核心差異在于是否需要審核:
- 直接分配:一級(城市合伙人)向二級(銷售合伙人)分配產(chǎn)品,無需審核,直接生效;
- 間接分配:二級(銷售合伙人)向三級(流量合伙人)分配產(chǎn)品,必須經(jīng)過對應(yīng)一級(城市合伙人)審核,審核通過后分配才生效。
為提升城市合伙人的操作效率,小程序需在 “分配產(chǎn)品頁面” 為城市合伙人顯示待審核數(shù),實時提醒其待處理的間接分配申請,而未讀計數(shù)的存儲與管理是實現(xiàn)該功能的核心。
二、未讀計數(shù)的實現(xiàn)方案
1. 核心觸發(fā)邏輯
在 “間接分配審核接口” 的最后,通過一行代碼觸發(fā)未讀計數(shù)更新,直接調(diào)用工具類完成城市合伙人未讀數(shù)量的累加:
// 添加未讀數(shù)(默認新增1條待審核提醒) appletRedisUtil.addUnreadCount(cityPartner.getId());
2. 核心工具類:AppletRedisUtil
工具類基于 Redis 實現(xiàn)未讀計數(shù)的 “新增、查詢、重置” 全流程管理,代碼與邏輯解析如下:
import jakarta.annotation.Resource;
import org.springblade.business.constant.RedisKeyConstant;
import org.springblade.business.pojo.entity.ProductApplyRecord;
import org.springblade.business.service.ProductApplyRecordService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Component // 注入Spring容器,全局可用
public class AppletRedisUtil {
@Resource
private RedisTemplate<String, Long> redisTemplate; // 操作Redis的核心組件
// 1. 重載方法:默認給城市合伙人新增1條未讀消息
public void addUnreadCount(Long miniUserId) {
addUnreadCount(miniUserId, 1L);
}
// 2. 核心方法:支持自定義新增未讀條數(shù),含數(shù)據(jù)準(zhǔn)確性校驗
public void addUnreadCount(Long miniUserId, Long value) {
// 2.1 工具類無法直接注入Service,通過Spring上下文獲取
ProductApplyRecordService productApplyRecordService = SpringContextUtil.getBean(ProductApplyRecordService.class);
// 2.2 查該城市合伙人的總申請數(shù)(未讀上限,避免未讀數(shù)超過實際總數(shù))
Long totalCount = productApplyRecordService.lambdaQuery()
.eq(ProductApplyRecord::getCityPartnerId, miniUserId)
.count();
// 2.3 查當(dāng)前Redis中的未讀數(shù)量(空值兜底返回0,避免空指針)
Long currentUnread = getUnreadCount(miniUserId);
// 2.4 修正未讀數(shù)量:若累加后超總申請數(shù),取總申請數(shù)(防止數(shù)據(jù)異常)
value = (currentUnread + value) > totalCount ? totalCount : (currentUnread + value);
// 2.5 更新Redis:用“常量前綴+用戶ID”作為key,原子自增未讀數(shù)量
redisTemplate.opsForValue().increment(RedisKeyConstant.PRODUCT_APPLY_UNREAD_NUM + miniUserId, value);
}
// 3. 查詢未讀數(shù)量:空值兜底,確保返回非null
public Long getUnreadCount(Long miniUserId) {
String key = RedisKeyConstant.PRODUCT_APPLY_UNREAD_NUM + miniUserId;
Long unread = redisTemplate.opsForValue().get(key);
return Objects.isNull(unread) ? 0L : unread;
}
// 4. 重置未讀數(shù)量:先置0再刪key,確保狀態(tài)徹底清空
public void resetUnreadCount(Long miniUserId) {
String key = RedisKeyConstant.PRODUCT_APPLY_UNREAD_NUM + miniUserId;
redisTemplate.opsForValue().set(key, 0L);
redisTemplate.delete(key);
}
}工具類核心特點
- 數(shù)據(jù)準(zhǔn)確性:通過 “總申請數(shù)校驗” 避免未讀數(shù)溢出,空值兜底避免空指針;
- 操作規(guī)范性:統(tǒng)一 Redis key 格式(常量前綴 + 用戶 ID),避免 key 混亂;
- 功能完整性:覆蓋 “新增、查詢、重置” 三大核心場景,支持默認 / 自定義新增條數(shù);
- 依賴合理性:通過 Spring 上下文獲取 Service,解決工具類無法直接注入的問題。
三、選型:為什么用 Redis 而非 MySQL?
未讀計數(shù)的核心訴求是 “快、并發(fā)安全、簡單”,Redis 完美匹配這些需求,而 MySQL 更擅長 “復(fù)雜查詢、事務(wù)一致性、永久存儲”,具體優(yōu)勢對比如下:
1. 性能碾壓:高頻場景響應(yīng)速度差 3 個量級
特性 | Redis(內(nèi)存數(shù)據(jù)庫) | MySQL(磁盤數(shù)據(jù)庫) |
響應(yīng)時間 | 微秒級(1μs = 10??秒) | 毫秒級(1ms = 10?³ 秒) |
每秒讀寫能力 | 數(shù)萬~數(shù)十萬次 | 千級次 |
高頻場景表現(xiàn) | 無卡頓,輕松扛住并發(fā)(如同時 100 個申請?zhí)峤唬?/p> | 易出現(xiàn) “查詢卡頓”“寫入排隊”,拖慢數(shù)據(jù)庫 |
2. 操作更輕量:避免 MySQL 復(fù)雜開銷
- Redis:用 increment 原子命令,1 行代碼完成 “未讀數(shù) + 1”,無需鎖 / 事務(wù);
- MySQL:需執(zhí)行 UPDATE xxx SET unread_count = unread_count + 1 WHERE ...,還需處理事務(wù)隔離級別、行鎖競爭,代碼繁瑣且開銷大。
3. 天然并發(fā)安全:解決 MySQL 更新沖突
當(dāng)多個請求同時修改同一城市合伙人的未讀計數(shù)時(如同時 2 條申請?zhí)峤唬?/p>
- Redis:INCR 是單線程原子操作,即使 100 個請求同時 + 1,結(jié)果也絕對正確(0→100);
- MySQL:易出現(xiàn) “并發(fā)更新丟失”(如兩個請求同時讀 5,都 + 1 后寫 6,實際應(yīng)是 7),需額外加 “樂觀鎖 / 悲觀鎖”,增加復(fù)雜度。
4. 緩存特性適配:減少數(shù)據(jù)庫壓力
- Redis:未讀計數(shù)是 “緩存”,所有讀寫走 Redis,MySQL 僅存原始申請記錄,極大降低 MySQL 訪問壓力;
- MySQL:若直接存儲未讀數(shù),高頻讀寫會占用數(shù)據(jù)庫資源,影響核心業(yè)務(wù)(如申請記錄查詢)。
5. 靈活擴展:支持更多交互場景
Redis 的特性可輕松滿足未來擴展需求,MySQL 難以實現(xiàn):
- 過期自動清理:給未讀計數(shù) key 設(shè) expire,實現(xiàn) “30 天未讀自動失效”,無需定時任務(wù);
- 批量操作:用 MSET/MGET 批量更新 / 查詢多個城市合伙人的未讀數(shù),效率極高;
- 豐富計數(shù)器操作:支持 INCRBY(自定義加量)、DECR(減量)、GETSET(獲取并重置),覆蓋全場景。
四、注意事項:Redis 數(shù)據(jù)安全兜底方案
雖然 Redis 是內(nèi)存數(shù)據(jù)庫,但工具類已做足數(shù)據(jù)安全保障,避免數(shù)據(jù)丟失:
- 數(shù)據(jù)源兜底:未讀計數(shù)的 “源頭” 是 MySQL(申請記錄存在 MySQL),Redis 僅為緩存;
- 異常修正:若 Redis 數(shù)據(jù)丟失,getUnreadCount 會返回 0,而 addUnreadCount 會重新查詢 MySQL 總申請數(shù),自動修正未讀計數(shù),不會失真。
到此這篇關(guān)于Redis實現(xiàn)未讀消息計數(shù)的示例代碼的文章就介紹到這了,更多相關(guān)Redis 未讀消息計數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis?HyperLogLog數(shù)據(jù)量統(tǒng)計的實現(xiàn)實例
在大數(shù)據(jù)時代,統(tǒng)計海量數(shù)據(jù)中的唯一值是一個常見的需求,但同時也是極具挑戰(zhàn)性的任務(wù),傳統(tǒng)的統(tǒng)計方法可能會消耗大量內(nèi)存或計算資源,而?Redis?的?HyperLogLog?數(shù)據(jù)結(jié)構(gòu)?則提供了一種高效、輕量的解決方案,下面就來詳細介紹一下HyperLogLog的使用,感興趣的可以了解一下2025-09-09
詳解Redis在SpringBoot工程中的綜合應(yīng)用
這篇文章主要介紹了Redis在SpringBoot工程中的綜合應(yīng)用,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-10-10
Redis?的內(nèi)存淘汰策略和過期刪除策略的區(qū)別
這篇文章主要介紹了Redis?的內(nèi)存淘汰策略和過期刪除策略的區(qū)別,Redis?是可以對?key?設(shè)置過期時間的,因此需要有相應(yīng)的機制將已過期的鍵值對刪除,而做這個工作的就是過期鍵值刪除策略2022-07-07
Springboot/Springcloud項目集成redis進行存取的過程解析
大家都知道Redis支持五種數(shù)據(jù)類型:string(字符串),hash(哈希),list(列表),set(集合),zset(sorted set:有序集合),本文重點給大家介紹Springboot/Springcloud項目集成redis進行存取的過程,需要的朋友參考下吧2021-12-12
Redis中哈希結(jié)構(gòu)(Dict)的實現(xiàn)
本文主要介紹了Redis中哈希結(jié)構(gòu)(Dict)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06

