《redis設計與實現》

陳不白發表於2020-11-01

提高系統架構的效能,增加快取層是常見的優化方式,redis和memcache是當前採用較多的快取元件,redis被稱為資料結構資料庫
redis和memcache的區別:
redis和memcahce都是基於記憶體的key-value儲存
memcache的事件模型是多執行緒reactor模型, 效能更好,但是隻支援一種key-value型別,複雜的資料結構需要使用者自己做序列化
redis是單執行緒,但是支援更多的資料結構,並且支援持久化和主從複製

redis常作為網際網路高併發請時的中介軟體,但是會有以下常見的三種問題:
1.快取穿透:查詢的資料不存在,快取和資料庫中都沒有,大量的這種請求就會對資料庫造成壓力
解決方案:
  a.使用布隆過濾器,即點陣圖bitmap,儘可能將所有可能的不存在資料都儲存下來,過濾掉不存在的請求
  b.即使資料不存在,也要新增到redis快取裡,將value設成空,避免頻繁訪問資料庫
2.快取擊穿:查詢的某一條熱點資料在快取中已過期,此時有大量針對此條資料的訪問,由於快取查詢不到會造成都到資料庫中查詢,導致資料庫壓力飆升
解決方案:
  a.利用redis自帶的setnx實現分散式鎖,當key已過期時,加上分散式鎖,獲取到鎖就到資料庫中查詢並更新快取,獲取不到鎖說明有其他執行緒已經在查詢資料庫,睡眠一會嘗試再次從redis快取中查詢
3.快取雪崩:當redis重啟或者大量key同時全部過期,此時若有大量請求,稱為快取雪崩,會對資料庫造成更大的壓力
解決方案:
  a.和快取擊穿一樣,使用分散式鎖或者佇列減輕資料庫壓力,但是會造成請求堵塞
  b.針對大量key全部過期這種,可以在設定過期時間設定隨機值,防止同時過期

以下是redis的部分實現:

1.獨有字串結構封裝,大概類似std::string的實現,自動擴充套件,動態伸縮
2.redis字典使用雜湊表,兩張雜湊表支援rehash重新雜湊,採用漸進rehash,大量資料不能一次性重新雜湊完畢
3.redis使用的資料結構有動態字串、雙端連結串列、雜湊表、跳躍表、整數集合、壓縮列表
4.redis為鍵值儲存,鍵都是字串,值有五大物件,字串物件(SET)、列表物件(RPUSH)、雜湊物件(HSET)、集合物件(SADD)、有序集合物件(ZADD)
5.每種物件都有2種編碼方式,有序集合列表中可以使用整數集合或者ZSET結構,ZSET結構是由跳躍表加字典方式實現,跳躍表保證集合有序,插入logn,字典保證訪問O1
6.過期刪除支援毫秒、秒、具體時間,過期鍵刪除方式是惰性刪除加定期刪除
7.rdb支援手動備份,save阻塞,bgsave子程式建立不阻塞,rdb儲存資料結構,aof儲存命令可能重複,所以支援aof重寫採用子程式加重寫緩衝區去重
  兩種持久化方式的區別:
  rdb方式為定時快照方式,一次性儲存記憶體中所有資料,採用子程式不阻塞主程式,無資料重複,體積小,重新載入恢復也快,缺點是定時儲存過程中出現當機,相比aof會丟失更多資料
  aof方式每條命令都會立刻重新整理到aof檔案裡,資料儲存更完整,缺點是當機後重新載入檔案相比rdb較慢,另外aof開啟了強制同步磁碟的話redis效能相較rdb稍微有所降低
8.redis採用事件驅動,分為檔案事件和時間事件,其中檔案事件就是reactor模型,為單執行緒reactor模型(I/O多路複用+非阻塞I/O)
為什麼redis是單執行緒?
因為redis是純記憶體操作,並且內部資料結構設計的比較好,且內部耗時操作都採用子程式操作,所以cpu不是redis的瓶頸,既然cpu不是redis瓶頸,單執行緒又能減少鎖競爭消耗,所以使用單執行緒
8.redis支援主從複製、哨兵叢集、叢集節點部署
主從複製:提供資料備份功能,從節點複製主節點資料,但是隻有主節點提供服務,主節點當機,從節點立刻轉主,選主演算法是raft演算法,最先獲得其他半數以上節點支援的成為主節點
哨兵:redis高可用方案,負責主從複製故障轉移
叢集節點:每個節點都提供服務,每個節點協商分別處理不同的槽,也可以和主從複製結合使用,因為redis是單執行緒,當資料量大的時候,可以採用redis叢集多程式的方式加大吞吐量
9.redis也支援釋出與訂閱,可以用作訊息中介軟體,但是效率應該沒有kafka好
10.redis支援事務,具有原子性、一致性、永續性,但是redis不支援事務回滾,如果事務處理過程中某一條指令報錯,後續指令會繼續執行
11.redis還支援lua語言、排序、二進位制陣列、慢查詢、監視器

相關文章