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