Redis核心原理詳細解說

1、Redis為什麼這麼快

C語言編寫

網絡IO是nio

單線程避免瞭多線程上下文切換造成的性能損耗

在內存中運算速度快

2、Redis網絡模型

IO多路復用(reactor)

redis利用epoll實現IO多路復用,將連接信息和事件放到隊列中,依次放到文件事件分派器,事件分派器將事件分發給事件處理器。

3、Redis數據結構

4、Redis持久化

RDB快照(snapshot)

配置# save 60 1000 //關閉RDB隻需要將所有的save保存策略註釋掉即可

AOF(append-only file)

將修改的每一條指令記錄進文件appendonly.aof中(先寫入os cache,每隔一段時間fsync到磁盤)。

AOF重寫:AOF文件裡可能有太多沒用指令,所以AOF會定期根據內存的最新數據生成aof文件。AOF重寫redis會fork出一個子進程去做(與bgsave命令類似),不會對redis正常命令處理有太多影響。bgrewriteao手動重寫。

Redis 4.0 混合持久化:aof-use-rdb-preamble yes

如果開啟瞭混合持久化,AOF在重寫時,不再是單純將內存數據轉換為RESP命令寫入AOF文件,而是將重寫這一刻之前的內存做RDB快照處理,並且將RDB快照內容和增量的AOF修改內存數據的命令存在一起,都寫入新的AOF文件,新的文件一開始不叫appendonly.aof,等到重寫完新的AOF文件才會進行改名,覆蓋原有的AOF文件,完成新舊兩個AOF文件的替換。於是在 Redis 重啟的時候,可以先加載 RDB 的內容,然後再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,因此重啟效率大幅得到提升。

RDB與AOF區別

Redis數據備份策略

  • (1)寫crontab定時調度腳本,每小時都copy一份rdb或aof的備份到一個目錄中去,僅僅保留最近48小時的備份。
  • (2)每天都保留一份當日的數據備份到一個目錄中去,可以保留最近1個月的備份。
  • (3)每次copy備份的時候,都把太舊的備份給刪瞭。
  • (4)每天晚上將當前機器上的備份復制一份到其他機器上,以防機器損壞。

5、Redis管道(Pipeline)

客戶端可以一次性發送多個請求而不用等待服務器的響應,待所有命令都發送完後再一次性讀取服務的響應,這樣可以極大的降低多條命令執行的網絡傳輸開銷,管道執行多條命令的網絡開銷實際上隻相當於一次命令執行的網絡開銷。需要註意到是用pipeline方式打包命令發送,redis必須在處理完所有命令前先緩存起所有命令的處理結果。打包的命令越多,緩存消耗內存也越多。所以並不是打包的命令越多越好。

pipeline中發送的每個command都會被server立即執行,如果執行失敗,將會在此後的響應中得到信息;也就是pipeline並不是表達“所有command都一起成功”的語義,管道中前面命令失敗,後面命令不會有影響,繼續執行。

6、Redis使用lua腳本

  • 1、減少網絡開銷:本來5次網絡請求的操作,可以用一個請求完成,原先5次請求的邏輯放在redis服務器上完成。使用腳本,減少瞭網絡往返時延。這點跟管道類似。
  • 2、原子操作:Redis會將整個腳本作為一個整體執行,中間不會被其他命令插入。管道不是原子的,不過redis的批量操作命令(類似mset)是原子的。
  • 3、替代redis的事務功能:redis自帶的事務功能很雞肋,而redis的lua腳本幾乎實現瞭常規的事務功能,官方推薦如果要使用redis的事務功能可以用redis lua替代。

7、Redis分佈式鎖

nx通過共享內存實現

8、Redis主從架構

9、Redis哨兵架構

sentinel哨兵是特殊的redis服務,不提供讀寫服務,主要用來監控redis實例節點。

10、Redis集群

11、Redis優化

  • 1、redis配置

合理的配置最大連接數;最大,最小空閑數。

  • 2、規約
  • 3、慢日志

slowlog

Redis慢日志命令說明:
config get slow* #查詢有關慢日志的配置信息
config set slowlog-log-slower-than 20000 #設置慢日志使時間閾值,單位微秒,此處為20毫秒,即超過20毫秒的操作都會記錄下來,生產環境建議設置1000,也就是1ms,這樣理論上redis並發至少達到1000,如果要求單機並發達到1萬以上,這個值可以設置為100
config set slowlog-max-len 1024 #設置慢日志記錄保存數量,如果保存數量已滿,會刪除最早的記錄,最新的記錄追加進來。記錄慢查詢日志時Redis會對長命令做截斷操作,並不會占用大量內存,建議設置稍大些,防止丟失日志
config rewrite #將服務器當前所使用的配置保存到redis.conf
slowlog len #獲取慢查詢日志列表的當前長度
slowlog get 5 #獲取最新的5條慢查詢日志。慢查詢日志由四個屬性組成:標識ID,發生時間戳,命令耗時,執行命令和參數
slowlog reset #重置慢查詢日志
  • 4、操作系統配置

(1)vm.swapiness

如果linux內核版本<3.5,那麼swapiness設置為0,這樣系統寧願swap也不會oom killer(殺掉進程)

如果linux內核版本>=3.5,那麼swapiness設置為1,這樣系統寧願swap也不會oom killer

cat /proc/version #查看linux內核版本
echo 1 > /proc/sys/vm/swappiness
echo vm.swapiness=1 >> /etc/sysctl.conf
cat /proc/sys/vm/overcommitmemory echo "vm.overcommitmemory=1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1

(2)合理設置文件句柄數

ulimit -a #查看系統文件句柄數,看open files那項
ulimit -n 65535 #設置系統文件句柄數

12、Redis問題

緩存穿透

緩存穿透是指查詢一個根本不存在的數據,緩存層和存儲層都不會命中,通常出於容錯的考慮,如果從存儲層查不到數據則不寫入緩存層。緩存穿透將導致不存在的數據每次請求都要到存儲層去查詢,失去瞭緩存保護後端存儲的意義。

  • 第一,自身業務代碼或者數據出現問題。
  • 第二,一些惡意攻擊、爬蟲等造成大量空命中。

(1)緩存空對象

(2)佈隆過濾器

緩存失效(擊穿)

由於大批量緩存在同一時間失效可能導致大量請求同時穿透緩存直達數據庫,可能會造成數據庫瞬間壓力過大甚至掛掉,對於這種情況我們在批量增加緩存時最好將這一批數據的緩存過期時間設置為一個時間段內的不同時間。

緩存雪崩

  • (1)保證緩存層服務高可用性,比如使用Redis Sentinel或Redis Cluster。
  • (2)依賴隔離組件為後端限流熔斷並降級。比如使用Sentinel或Hystrix限流降級組件。比如服務降級,我們可以針對不同的數據采取不同的處理方式。當業務應用訪問的是非核心數據(例如電商商品屬性,用戶信息等)時,暫時停止從緩存中查詢這些數據,而是直接返回預定義的默認降級信息、空值或是錯誤提示信息;當業務應用訪問的是核心數據(例如電商商品庫存)時,仍然允許查詢緩存,如果緩存缺失,也可以繼續通過數據庫讀取。
  • (3)提前演練。在項目上線前,演練緩存層宕掉後,應用以及後端的負載情況以及可能出現的問題,在此基礎上做一些預案設定。

到此這篇關於Redis核心原理詳細解說的文章就介紹到這瞭,更多相關Redis原理內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: