Redis篇
Redis持久化方式
通常兩者結合一起使用
方式一:RDB
RDB全稱Redis數據備份文件,也叫作Redis數據快照。簡單的說就是把內存中的數據都記錄到磁盤
1、實現命令
- 手動
save # 由Redis主進程執行,會阻塞所有命令
bgsave # 開啟子進程執行,避免影響主進程
- 配置文件 redis.conf
save 100 1 # 指100秒內至少有一個key被修改時,則執行RDB備份
2、RDB執行原理
RDB執行時會從主進程fork一個子進程,子進程共享主進程的內存空間,實際上是復制了主進程的頁表,因此子進程就可以讀取內存中的數據到RDB文件中。
fork采用的是copy-on-write技術:
主進程讀時,訪問共享空間
主進程寫時,復制一份副本,再進行寫操作
方式二:AOF
AOF全稱追加文件,Redis處理的每一個寫命令都會記錄在AOF文件中
1、開啟AOF模式
默認關閉,開啟需在redis.conf文件中進行配置:
appendonly=yes,
appendfilename="aofile.aof"
2、AOF記錄的頻率(又稱刷盤策略)
在redis.conf文件中配置:
appendfsync always# 每執行一次寫命令,立即寫入AOF文件
appendfsync everysec(默認) # 寫命令執行完先放入緩沖區,每隔1秒從緩沖區寫入AOF文件
appendfsync no# 寫命令執行完先放入緩沖區,由操作系統決定何時寫入AOF文件
3、命令重寫
由于AOF是記錄命令,通常空間占用會高的多,可以使用
命令重寫的策略來縮小文件體積,在redis.conf文件中配置如下:
# AOF文件比上次文件 增長超過多少百分比則觸發重寫
auto-aof-rewrite-percentage 100
# AOF文件體積最小多大以上才觸發重寫
auto-aof-rewrite-min-size 64mb
兩種持久化方式對比

Redis數據過期策略
主要有
惰性刪除和定時刪除兩種,定時刪除又分為兩種模式:SLOW和FAST模式通常兩者結合一起使用
1、惰性刪除
當key過期后,不立即刪除,而是等到需要使用該key時,再進行檢查并刪除過期key
優點:對CPU友好
缺點:過期key積累對內存占用不友好
2、定時刪除
每隔一段時間,就隨機的對一些key進行檢查,并刪除過期key
SLOW:SLOW模式是定時任務,執行頻率默認為10hz,每次不超過25ms,以通過修改配置文件redis.conf 的hz選項來調整這個次數
FAST:FAST模式執行頻率不固定,但兩次間隔不低于2ms,每次耗時不超過1ms
Redis數據淘汰策略
LRU: 最近最少使用算法。用當前時間減去最后一次訪問時間,這個值越大則淘汰優先級越高
LFU: 最少頻率使用。會統計每個key的訪問頻率,值越小淘汰優先級越高redis提供了8中數據淘汰策略:
- noeviction
默認策略,不淘汰任何key,但是內存滿時不允許寫入新數據,并且會直接報錯
- allkeys-lru
對全體key,基于LRU算法進行淘汰
- volatile-lru
對設置了TTL的key,基于LRU算法進行淘汰
- allkeys-lfu
對全體key,基于LFU算法進行淘汰
- 對設置了TTL的key,基于LFU算法進行淘汰
分布式鎖
使用redisson集成的分布式鎖有三大好處:
- 提供watchdog監控執行線程,可實現
鎖自動續期,默認10秒一次- 其他線程想要加鎖,會進行一定次數的
阻塞循環等待- 底層基于
LUA腳本,實現了原子操作可重入,在redis中進行存儲的時候使用的hash結構,來存儲線程信息和重入的次數,多個鎖重入需要判斷是否是當前線程,主要是根據線程ID進行判斷缺點:
不能實現
主從一致性解決方案:
紅鎖,缺點是會導致性能變低- 采用
zonkeeper實現的CP思想的分布式鎖

代碼實現:
// 1.構造redisson實現分布式鎖必要的Config
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:5379").setPassword("123456").setDatabase(0);
// 2.構造RedissonClient
RedissonClient redissonClient = Redisson.create(config);
// 3.獲取鎖對象實例(無法保證是按線程的順序獲取到)
RLock rLock = redissonClient.getLock(lockKey);
try {
/**
* 4.嘗試獲取鎖
* waitTimeout 嘗試獲取鎖的最大等待時間,超過這個值,則認為獲取鎖失敗
* leaseTime 鎖的持有時間,超過這個時間鎖會自動失效(值應設置為大于業務處理的時間,確保在鎖有效期內業務能處理完)
*/
boolean res = rLock.tryLock((long)waitTimeout, (long)leaseTime, TimeUnit.SECONDS);
if (res) {
//成功獲得鎖,在這里處理業務
}
} catch (Exception e) {
throw new RuntimeException("aquire lock fail");
}finally{
//無論如何, 最后都要解鎖
rLock.unlock();
}
如何保證Redis的高并發高可用
一、高并發
要想提高redis的并發能力,就需要搭建
主從集群,實現讀寫分離,主節點用于寫操作,從節點用于讀操作
主從數據同步
從節點第一次與主節點建立連接時使用
全量同步

二、高可用
如果只是單純的主從集群模式,并不能保證Redis的高可用性,因此Redis提供了一種保證高可用的
哨兵機制,來實現主從集群的自動故障恢復哨兵機制的三大特點:
- 監控:Sentinel會不斷檢查master和slave是否按預期工作,Sentinel基于心跳機制監測服務狀態,每隔1秒向集群的每個實例發送ping命令
- 自動故障恢復:如果master故障,Sentinel會將一個slave提升為master。當故障實例恢復后也以新的master為主
- 通知:Sentinel充當Redis客戶端的服務發現來源,當集群發生故障轉移時,會將最新信息推送給Redis的客戶端以連接新的master
哨兵模式結構:
腦裂問題
使用哨兵模式時,當master網絡卡頓時,選取了一個從節點作為主節點,但是舊的master在網絡恢復后處理了之前的寫操作,更新了數據,而新master為了同步從節點的數據,把老master的數據清空了,從而導致數據丟失,這種就叫做
腦裂問題
- 解決方法
只需要在redis配置文件中配置
min-replicas-to-write 1 # 表示最少的salve節點為1個
min-replicas-max-lag 5 # 表示數據復制和同步的延遲不能超過5秒
三、分片集群
前面主從哨兵模式解決了高并發高可用的問題,但是仍有兩個問題沒有解決
:
海量數據存儲問題
高并發寫的問題
使用分片集群可以解決上述問題,分片集群特征
:
集群中有多個master,每個master保存不同數據
每個master都可以有多個slave節點
master之間通過ping監測彼此健康狀態
客戶端請求可以訪問集群任意節點,最終都會被轉發到正確節點
PS:Redis 分片集群引入了哈希槽的概念,Redis 集群有 16384 個哈希槽,每個 key通過 CRC16 校驗后對 16384 取模來決定放置哪個槽,集群的每個節點負責一部分 hash 槽。
Redis是單線程,為什么還能這么快
原因很簡單:
Redis是純內存操作,執行速度非常快,并且基于C語言實現
采用單線程,避免不必要的上下文切換可競爭條件,多線程還要考慮線程安全問題
使用I/O多路復用模型,非阻塞IO
四、Redis網絡模型


浙公網安備 33010602011771號