Redis
Redis 是一個(gè)key-value 存儲(chǔ)系統(tǒng)。
Redis支持五種數(shù)據(jù)類型:
string (字符串)
list (列表)
hash (hash表)
set (集合)
zset (有序集合)
和memcached 類似,redis 支持的數(shù)據(jù)類型更豐富、數(shù)據(jù)能持久化。
memcached 把數(shù)據(jù)全部存儲(chǔ)在內(nèi)存中,斷電后會(huì)掛掉,數(shù)據(jù)不能超過內(nèi)存大小。
而redis`數(shù)據(jù)會(huì)定期備份到硬盤上。
落地策略
RDB 持久化(snapshotting ):快照,整體備份。在指定的時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤,實(shí)際上是fork 一個(gè)子線程,先將數(shù)據(jù)集寫入臨時(shí)文件,寫入成功后,再替換之前的文件,用二進(jìn)制壓縮存儲(chǔ)。
AOF 持久化(append-only-file ):以日志的形式記錄服務(wù)器所處理的每一個(gè)寫、刪除操作,查詢操作不會(huì)記錄,以文本的方式記錄,可以打開文件看到詳細(xì)的操作記錄。
過期策略
- 定期刪除:
redis 會(huì)把設(shè)置了過期時(shí)間的key 放在單獨(dú)的字典中,定時(shí)遍歷來刪除到期的key
- 每100ms從過期字典中隨機(jī)挑選20個(gè),把其中過期的
key 刪除
- 如果過期的
key 占比超過1/4,重復(fù)步驟1
- 惰性刪除
- 過期的
key 并不一定會(huì)馬上刪除,還會(huì)占用著內(nèi)存。當(dāng)你真正查詢這個(gè)key 時(shí),redis 會(huì)檢查一下,這個(gè)設(shè)置了過期時(shí)間的key 是否過期了,如果過期了就會(huì)刪除,返回空。
- 內(nèi)存淘汰機(jī)制
當(dāng)redis 內(nèi)存超出物理內(nèi)存限制時(shí),會(huì)和磁盤產(chǎn)生swap ,這種情況性能極差,一般是不允許的。
(1)noeviction :拒絕寫操作,讀、刪除可以正常使用。默認(rèn)策略
(2)allkeys-lru :移除最近最少使用的key ,最常用的策略
(3)allkeys-random :隨機(jī)刪除某個(gè)key
(4)volatile-lru :在設(shè)置了過期時(shí)間的key 中,移除最近最少使用的key
(5)volatile-random :在設(shè)置了過期時(shí)間的key 中,隨機(jī)刪除某個(gè)key
(6)volatile-ttl :在設(shè)置了過期時(shí)間的key 中,把最早要過期的key 優(yōu)先刪除
Redis 緩存和MySQL 數(shù)據(jù)一致性方案
在高并發(fā)的業(yè)務(wù)場景下,數(shù)據(jù)庫大多數(shù)情況都是用戶并發(fā)訪問最薄弱的環(huán)節(jié)。所以,就需要使用redis 做一個(gè)緩沖操作,讓請求先訪問到redis ,而不是直接訪問MySQL 數(shù)據(jù)庫
請求先訪問redis 緩存,如果緩存中有數(shù)據(jù),直接加載數(shù)據(jù),如果緩存中沒有數(shù)據(jù),再訪問數(shù)據(jù)庫,數(shù)據(jù)庫會(huì)將數(shù)據(jù)放入redis 中,然后加載數(shù)據(jù)。
讀取緩存一般沒有什么問題,但是一旦涉及到數(shù)據(jù)更新:數(shù)據(jù)庫和緩存更新,就容易出現(xiàn)緩存redis 和數(shù)據(jù)庫MySQL 間的數(shù)據(jù)一致性問題。
- 如果先刪除了緩存
Redis ,還沒有來得及寫庫MySQL ,另一個(gè)線程就來讀取,發(fā)現(xiàn)緩存為空,則去數(shù)據(jù)庫中讀取數(shù)據(jù)寫入緩存,此時(shí)緩存中沒臟數(shù)據(jù)。
- 如果先寫了庫,在刪除緩存之前,寫庫的線程宕機(jī)了,沒有刪除掉緩存,則也會(huì)出現(xiàn)數(shù)據(jù)不一致情況。
因?yàn)閷懞妥x是并發(fā)的,沒法保證順序,就會(huì)出現(xiàn)緩存和數(shù)據(jù)庫的數(shù)據(jù)不一致的問題。
解決方案:異步更新緩存(基于訂閱binlog 的同步機(jī)制)
MySQL 的binlog 增量訂閱消費(fèi)+消息隊(duì)列+增量數(shù)據(jù) 更新到redis 。
(1)讀redis :熱數(shù)據(jù)基本都在redis
(2)寫MySQL :增刪改都是操作MySQL
(3)更新redis 數(shù)據(jù):MySQL 的數(shù)據(jù)操作binlog ,來更新到redis
注意:MySQL 實(shí)現(xiàn)主從一致性,也是基于訂閱binlog 來實(shí)現(xiàn)增量操作。
binlog :是MySQL 的二進(jìn)制文件,用于記錄MySQL 的數(shù)據(jù)更新(insert 、update 、delete 操作)。
|