Redis分布式緩存與秒殺
一、單點(diǎn)Redis的問(wèn)題
1、數(shù)據(jù)丟失問(wèn)題
Redis數(shù)據(jù)持久化。
2、并發(fā)能力問(wèn)題
大家主從集群,實(shí)現(xiàn)讀寫分離。
3、故障恢復(fù)問(wèn)題
利用Redis哨兵,實(shí)現(xiàn)健康檢測(cè)和自動(dòng)恢復(fù)。
4、存儲(chǔ)能力問(wèn)題
搭建分片集群,利用插槽機(jī)制實(shí)現(xiàn)動(dòng)態(tài)擴(kuò)容。
二、RDB
RDB全稱Redis Database Backup file(Redis數(shù)據(jù)備份文件),也被叫做Redis數(shù)據(jù)快照。簡(jiǎn)單來(lái)說(shuō)就是把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中。當(dāng)Redis實(shí)例故障重啟后,從磁盤讀取快照文件,恢復(fù)數(shù)據(jù)。
快照文件稱為RDB文件,默認(rèn)是保存在當(dāng)前運(yùn)行目錄。
Redis內(nèi)部有觸發(fā)RDB的機(jī)制,可以在redis.conf文件中找到,格式如下:
bgsave開始時(shí)會(huì)fork主進(jìn)程得到子進(jìn)程,子進(jìn)程共享主進(jìn)程的內(nèi)存數(shù)據(jù)。完成fork后讀取內(nèi)存數(shù)據(jù)并寫入 RDB 文件。
fork采用的是copy-on-write技術(shù):
- 當(dāng)主進(jìn)程執(zhí)行讀操作時(shí),訪問(wèn)共享內(nèi)存;
- 當(dāng)主進(jìn)程執(zhí)行寫操作時(shí),則會(huì)拷貝一份數(shù)據(jù),執(zhí)行寫操作;
RDB方式bgsave的基本流程?
- fork主進(jìn)程得到一個(gè)子進(jìn)程,共享內(nèi)存空間;
- 子進(jìn)程讀取內(nèi)存數(shù)據(jù)并寫入新的RDB文件;
- 用新RDB文件替換舊的RDB文件;
RDB會(huì)在什么時(shí)候執(zhí)行?save 60 1000代表什么含義?
- 默認(rèn)是服務(wù)停止時(shí);
- 代表60秒內(nèi)至少執(zhí)行1000次修改則觸發(fā)RDB;
RDB的缺點(diǎn)?
- RDB執(zhí)行間隔時(shí)間長(zhǎng),兩次RDB之間寫入數(shù)據(jù)有丟失的風(fēng)險(xiǎn);
- fork子進(jìn)程、壓縮、寫出RDB文件都比較耗時(shí);
AOF的命令記錄的頻率也可以通過(guò)redis.conf文件來(lái)配:
三、AOF
AOF全稱為Append Only File(追加文件)。Redis處理的每一個(gè)寫命令都會(huì)記錄在AOF文件,可以看做是命令日志文件。
AOF默認(rèn)是關(guān)閉的,需要修改redis.conf配置文件來(lái)開啟AOF:
AOF的命令記錄的頻率也可以通過(guò)redis.conf文件來(lái)配:
配置項(xiàng) | 刷盤時(shí)機(jī) | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|---|
Always | 同步刷盤 | 可靠性高,幾乎不丟數(shù)據(jù) | 性能影響大 |
everysec | 每秒刷盤 | 性能適中 | 最多丟失一分鐘的數(shù)據(jù) |
no | 操作系統(tǒng)控制 | 性能最好 | 可靠性較差,可能丟失大量數(shù)據(jù) |
因?yàn)槭怯涗浢?,AOF文件會(huì)比RDB文件大的多。而且AOF會(huì)記錄對(duì)同一個(gè)key的多次寫操作,但只有最后一次寫操作才有意義。通過(guò)執(zhí)行bgrewriteaof命令,可以讓AOF文件執(zhí)行重寫功能,用最少的命令達(dá)到相同效果。
set id 1 set name nezha set id 2 bgrewriteaof mset name nezha id 2
Redis也會(huì)在觸發(fā)閾值時(shí)自動(dòng)去重寫AOF文件。閾值也可以在redis.conf中配置:
# AOF文件比上次文件 增長(zhǎng)超過(guò)多少百分比則觸發(fā)重寫auto-aof-rewrite-percentage 100# AOF文件體積最小多大以上才觸發(fā)重寫 auto-aof-rewrite-min-size 64mb
RDB和AOF各有自己的優(yōu)缺點(diǎn),如果對(duì)數(shù)據(jù)安全性要求較高,在實(shí)際開發(fā)中往往會(huì)結(jié)合兩者來(lái)使用。
RDB | AOF | |
---|---|---|
持久化方式 | 定時(shí)對(duì)整個(gè)內(nèi)存做快照 | 記錄每一次執(zhí)行的命令 |
數(shù)據(jù)完整性 | 不完整,兩次備份之間會(huì)丟失 | 相對(duì)完整,取決于刷盤策略 |
文件大小 | 會(huì)有壓縮,文件體積小 | 記錄命令,文件體積很大 |
宕機(jī)恢復(fù)速度 | 很快 | 慢 |
數(shù)據(jù)恢復(fù)優(yōu)先級(jí) | 低,因?yàn)閿?shù)據(jù)完整性不低 | 高,因?yàn)閿?shù)據(jù)完整性更高 |
系統(tǒng)資源占用 | 高,大量CPU和內(nèi)存消耗 | 低,主要是磁盤IO資源,但AOF重寫時(shí)會(huì)占用大量CPU和內(nèi)存資源 |
使用場(chǎng)景 | 可以容忍數(shù)分鐘的數(shù)據(jù)丟失,追求更快的啟動(dòng)速度 | 對(duì)數(shù)據(jù)安全性要求較高常見 |
四、Redis優(yōu)化秒殺流程
1、秒殺步驟:
- 查詢優(yōu)惠券;
- 判斷秒殺商品庫(kù)存;
- 查詢訂單
- 校驗(yàn)一人一單;
- 減庫(kù)存;
- 創(chuàng)建訂單;
2、Redis優(yōu)化秒殺步驟:
- 新增秒殺的優(yōu)惠券,將優(yōu)惠券信息保存到Redis中;
- 基于Lua腳本,判斷秒殺商品庫(kù)存,一人一單,決定用戶是否秒殺成功;
- 如果秒殺成功,將優(yōu)惠券id、用戶id、商品id封裝到阻塞隊(duì)列中;
- 開啟異步任務(wù),不斷從阻塞隊(duì)列中讀取信息,實(shí)現(xiàn)異步下單功能;
3、秒殺的lua腳本
4、調(diào)用秒殺的lua腳本
public Result seckillVoucher(Long voucherId) { Long userId = UserHolder.getUser().getId(); long orderId = redisIdWorker.nextId("order"); // 1.執(zhí)行l(wèi)ua腳本 Long result = stringRedisTemplate.execute( SECKILL_SCRIPT, Collections.emptyList(), voucherId.toString(), userId.toString(), String.valueOf(orderId) ); int r = result.intValue(); // 2.判斷結(jié)果是否為0 if (r != 0) { // 2.1.不為0 ,代表沒(méi)有購(gòu)買資格 return Result.fail(r == 1 ? "庫(kù)存不足" : "不能重復(fù)下單"); } // 3.返回訂單id return Result.ok(orderId); }
5、通過(guò)線程池,操作阻塞隊(duì)列
// 線程池 private static final ExecutorService SECKILL_ORDER_EXECUTOR = Executors.newSingleThreadExecutor(); /** * 在類初始化完成后執(zhí)行 */ @PostConstruct private void init() { SECKILL_ORDER_EXECUTOR.submit(new VoucherOrderHandler()); } // 阻塞隊(duì)列 private BlockingQueue<VoucherOrder> orderTasks = new ArrayBlockingQueue<>(1024 * 1024); private class OrderHandler implements Runnable{ @Override public void run() { while (true){ try { doSomething(); } catch (Exception e) { log.error("處理訂單異常", e); } } } }
五、基于Redis實(shí)現(xiàn)共享session登錄
基于session實(shí)現(xiàn)登錄
基于Redis實(shí)現(xiàn)共享session登錄
public class RefreshTokenInterceptor implements HandlerInterceptor { private StringRedisTemplate stringRedisTemplate; public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) { this.stringRedisTemplate = stringRedisTemplate; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1、獲取請(qǐng)求頭中的token String token = request.getHeader("authorization"); if (StrUtil.isBlank(token)) { return true; } // 2、基于TOKEN獲取redis中的用戶 String key = LOGIN_USER_KEY + token; Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(key); // 3、判斷用戶是否存在 if (userMap.isEmpty()) { return true; } // 5、將查詢到的hash數(shù)據(jù)轉(zhuǎn)為UserDTO UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false); // 6、存在,保存用戶信息到 ThreadLocal UserHolder.saveUser(userDTO); // 7、刷新token有效期 stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES); // 8、放行 return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 移除用戶 UserHolder.removeUser(); } }
到此這篇關(guān)于Redis分布式緩存與秒殺的文章就介紹到這了,更多相關(guān)Redis分布式緩存秒殺內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Redis在SpringBoot工程中的綜合應(yīng)用
這篇文章主要介紹了Redis在SpringBoot工程中的綜合應(yīng)用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10Redis 安裝 redistimeseries.so(時(shí)間序列數(shù)據(jù)類型)的配置步驟
這篇文章主要介紹了Redis 安裝 redistimeseries.so(時(shí)間序列數(shù)據(jù)類型)詳細(xì)教程,配置步驟需要先下載redistimeseries.so 文件,文中介紹了啟動(dòng)失敗問(wèn)題排查,需要的朋友可以參考下2024-01-01redis客戶端實(shí)現(xiàn)高可用讀寫分離的方式詳解
基于sentienl 獲取和動(dòng)態(tài)感知 master、slaves節(jié)點(diǎn)信息的變化,我們的讀寫分離客戶端就能具備高可用+動(dòng)態(tài)擴(kuò)容感知能力了,接下來(lái)通過(guò)本文給大家分享redis客戶端實(shí)現(xiàn)高可用讀寫分離的方式,感興趣的朋友一起看看吧2021-07-07Ubuntu22.04 LTS 上安裝Redis的過(guò)程
Redis是一種開源的內(nèi)存數(shù)據(jù)存儲(chǔ),可以用作數(shù)據(jù)庫(kù)、緩存和消息代理等,本文將會(huì)介紹兩種不同的安裝方式,包括從源代碼編譯安裝以及通過(guò)apt包管理器安裝,需要的朋友參考下吧2023-11-11Redis遍歷所有key的兩個(gè)命令(KEYS 和 SCAN)
這篇文章主要介紹了Redis遍歷所有key的兩個(gè)命令(KEYS 和 SCAN),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Redis數(shù)據(jù)庫(kù)的數(shù)據(jù)傾斜詳解
Redis,英文全稱是Remote Dictionary Server(遠(yuǎn)程字典服務(wù)),是一個(gè)開源的使用ANSI C語(yǔ)言編寫、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型、Key-Value數(shù)據(jù)庫(kù),需要的朋友可以參考下2023-07-07Windows操作系統(tǒng)下Redis服務(wù)安裝圖文教程
這篇文章主要介紹了Windows操作系統(tǒng)下Redis服務(wù)安裝圖文教程,文中給大家提供了redis的下載地址,安裝程序步驟,需要的朋友可以參考下2018-03-03Govern Service 基于 Redis 的服務(wù)治理平臺(tái)安裝過(guò)程詳解
Govern Service 是一個(gè)輕量級(jí)、低成本的服務(wù)注冊(cè)、服務(wù)發(fā)現(xiàn)、 配置服務(wù) SDK,通過(guò)使用現(xiàn)有基礎(chǔ)設(shè)施中的 Redis 不用給運(yùn)維部署帶來(lái)額外的成本與負(fù)擔(dān),接下來(lái)通過(guò)本文給大家分享Govern Service 基于 Redis 的服務(wù)治理平臺(tái)的相關(guān)知識(shí),感興趣的朋友一起看看吧2021-05-05