Redis系列(十四)、Redis6新特性之RESP3与客户端缓存(Client side caching)
Redis6引入新的RESP3協議,并以此為基礎加入了客戶端緩存的新特性,在此特性下,大大提高了應用程序的響應速度,并降低了數據庫的壓力,本篇就帶大家來看一下Redis6的新特性:客戶端緩存。
目錄
什么是客戶端緩存
什么是RESP3
客戶端緩存的實現方式
默認模式
原理?
應用
廣播模式
原理
應用
重定向模式
OPTIN 和 OPTOUT
NOLOOP選項
失效表key上限
Redis6系列文章:
Redis系列(一)、CentOS7下安裝Redis6.0.3穩定版
Redis系列(二)、數據類型之字符串String?
Redis系列(三)、數據類型之哈希Hash
Redis系列(四)、數據類型之列表List
Redis系列(五)、數據類型之無序集合Set
Redis系列(六)、數據類型之有序集合ZSet(sorted_set)
Redis系列(七)、常用key命令
Redis系列(八)、常用服務器命令?
Redis系列(九)、Redis的“事務”及Lua腳本操作
Redis系列(十)、詳解Redis持久化方式AOF、RDB以及混合持久化
Redis系列(十一)、Redis6新特性之ACL安全策略(用戶權限管理)
Redis系列(十二)、Redis6集群搭建及原理(主從、哨兵、集群)
Redis系列(十三)、pub/sub發布與訂閱(對比List和Kafka)
Redis系列(十四)、Redis6新特性之RESP3與客戶端緩存(Client side caching)
?
什么是客戶端緩存
?
客戶端緩存是一種用于創建高性能服務的技術,在此技術下,應用程序端將數據庫中的數據緩存在應用端的內存中,當應用程序訪問數據時直接從本機內存中讀取,而無需連接數據庫端,減少了網絡IO,提升了應用程序的響應速度,同時也減少了數據庫端的壓力。
官網:https://redis.io/topics/client-side-caching
Why RESP3:?http://antirez.com/news/125
沒有客戶端緩存:
應用端先查詢Redis端,如果沒有Redis緩存則到原數據庫端查詢,如果有則直接從Redis端查詢數據,更新數據時直接更新MySQL端并同步到Redis內;
有客戶端緩存:
應用端先查詢本地緩存如Guava、Caffeine,若沒有本地緩存則訪問Redis緩存,如果Redis緩存中也沒有則查詢原數據庫;
客戶端緩存的優點:
? ? 1.降低了客戶端的數據延遲,提升客戶端的響應速度;
? ? 2.數據庫端接收的查詢減少,降低了數據庫端的壓力,因此在相同的數據集下可以使用更少的節點提供服務;
疑問:
為了實現客戶端緩存,我們面臨這樣的問題,當進程中緩存了數據,而數據庫端數據發生變更,該如何通知到進程,避免客戶端顯示失效的數據呢? 在Redis中可以使用上篇介紹過的發布訂閱機制,向客戶端發布數據失效的通知,但該模式下即使某些客戶端中沒有包含過期數據也會向所有客戶端發送無效的消息,非常影響數據庫的性能。
在之前的版本中,客戶端緩存采用緩存槽(caching slot)的方式記錄每個客戶端內的key是否發生變化以及時同步,最新版中已棄用該方式,而是采用記錄key的名稱或前綴。
什么是RESP3
RESP全程RedisSerializationProtocol,是Redis服務端與客戶端之間通信的協議。在Redis6之前的版本,使用的是RESP2協議,數據都是以字符串數組的形式返回給客戶端,不管是list還是sorted set。因此客戶端需要自行去根據類型進行解析,這樣會增加了客戶端實現的復雜性。
為了照顧老用戶,Redis6在兼容 RESP2 的基礎上,開始支持 RESP3,但未來會全面切換到RESP3之上。今天的客戶端緩存在基于RESP3才能有更好的實現,可以在同一個連接中運行數據的查詢和接收失效消息。而目前在RESP2上實現的客戶端緩存,需要兩個客戶端連接以轉發重定向的形式實現。
在Redis6中我們可以使用HELLO命令在RESP2和RESP3協議之間進行切換:
#使用RESP2協議
HELLO 2
#使用RESP3協議
HELLO 3
客戶端緩存的實現方式
Redis客戶端緩存被稱為Tracking,在RESP3協議下,有兩種模式:
默認模式:服務器記錄客戶端訪問了哪些key,當其中的key發生變更時給客戶端發送失效信息,消耗服務器端內存;
廣播模式:客戶端訂閱訪問過的key的前綴,當符合模式的key發生變更就會被通知(即使變更的key沒有被客戶端緩存),服務器端不記錄客戶端訪問的key,因此不會消耗服務器端的內存;
默認模式
原理?
服務器端會記錄訪問key的客戶端列表并維護一個表,這個表被稱為失效表(Invalidation Table),如果插入一個新的key,服務器端會給客戶端發送失效信息并從客戶端剔除該key,避免提供過時數據。
在失效表中不會記錄key和客戶端內對應指針的映射關系,只會記錄key的指針和各客戶端ID(每個Redis客戶端都有一個唯一ID)的映射關系,當發送完失效信息后,客戶端剔除key,服務端從失效表中刪除key的指針和客戶端ID的映射關系。
在失效表中key的命名空間只有一個,即是說,在db0~db15中相同的key名,在失效表中會記錄在同一個命名空間內,即使客戶端緩存的是db0內的key,如果db1內的同名key被更新,也會通知客戶端剔除db0內的同名key。
客戶端緩存的操作就是對key的內存地址進行操作:?
1.當開啟客戶端緩存的客戶端從Redis獲取數據時,Redis服務端會調用enableTracking方法在上面的失效表中記錄key和客戶端ID的映射關系;
2.若key被修改,則Redis服務端會調用trackingInvalidateKey函數根據該key被緩存的客戶端列表ID調用sendTrackingMessage函數向它們發送失效消息。(發送失效消息前會檢查客戶端的Client_Tracking和NOLOOP狀態)
3.服務端發送完失效消息后會從失效表中將該key與客戶端ID的映射關系刪除;
4.由于客戶端可能會在開啟之后關閉了緩存功能,在失效表中刪除key和該客戶端ID之間的映射關系比較消耗性能,因此服務端采用懶刪除的方式,只是將該客戶端的Client_Tracking相關標志位刪除;
應用
上面提到我們可以使用HELLO命令切換RESP3協議,在此協議下我們使用tracking命令開啟track追蹤,此時服務端會記錄客戶端在連接的生命周期內的只讀的key,當客戶端開啟track追蹤后,key的數據會被緩存在客戶端內存中:
#開啟RESP3協議
HELLO 3
#開啟tracking客戶端緩存
client tracking on
#關閉tracking客戶端緩存
client tracking off
為了演示失效消息的通知,這里使用telnet測試客戶端緩存,然后在另一個redis-cli對key做操作:
# 使用telnet連接客戶端 telnet wykd 6379#auth命令登錄服務器(如果沒有密碼可以忽略) auth default wyk123456#開啟RESP3 hello 3#開啟客戶端緩存tracking client tracking on#查詢一個key 同時該key會被緩存 get name#在另一個redis客戶端中 修改/刪除/過期/淘汰 該key set name new_values#在telnet窗口會受到key失效的消息如下: get nam #客戶端緩存key$3 wyk>2 # 失效消息 $10 invalidate *1 $4 name#關閉客戶端緩存tracking,關閉后不會再收到key的失效消息 client tracking off當開啟了tracking后,客戶端緩存的key如果在別處被修改為與原值一樣,也會收到失效消息;
當客戶端緩存失效后,該key再被修改時,客戶端不會再收到消息,也就是再查詢該key之后才會在客戶端緩存key的值;
當客戶端緩存的key因過期策略或內存淘汰策略被驅逐時,服務端也會發送失效消息給開啟了tracking的客戶端:
當開啟了tracking的客戶端獲取的key不存在時,如果在另一個客戶端新增/修改了該key,那個tracking的客戶端也會收到失效消息,可見如果key不存在也會在客戶端緩存中緩存空值,這種結果因人而異,個人認為這樣不太好,一是客戶端會徒增大量的無用緩存,而是服務端的失效表會維護更多的key->clientID的映射關系。
廣播模式
原理
另一個客戶端緩存的實現方式是廣播模式(broadcasting),廣播不會消耗服務端的內存,而是向各客戶端發送更多的失效消息。廣播模式與默認模式類似,不同的是廣播模式下維護的是前綴表,在前綴表中存儲客戶端訂閱的key前綴與客戶端ID之間的映射關系。
在這種模式下,有以下的主要行為:
?
1.客戶端使用BCAST選項開啟客戶端緩存的廣播模式,并使用PREFIX指定一個或多個前綴。如果不指定前綴則默認客戶端接收所有的key的失效消息,如果指定則只會接收匹配該前綴的key的失效消息;
2.在廣播模式下,服務端維護的不是失效表,而是前綴表(Prefix Table),每個前綴映射一些客戶端ID;
3.每次修改跟任意前綴匹配的鍵時,所有訂閱該前綴的客戶端都將收到失效消息;
4.服務端的CPU消耗與訂閱的key前綴數量成正比,訂閱的key前綴數量越多服務器端壓力越大;
5.服務器可以為訂閱特定前綴的客戶端創建單個回復,并向所有的客戶端發送相同的回復來進行優化,有助于降低CPU使用率。
應用
同樣,在廣播模式下也需要開啟RESP3協議,這里我們仍然使用剛才的telnet會話進行演示。
使用下面的命令開啟廣播模式的客戶端緩存,上面提到廣播模式下服務端維護一個前綴表,記錄key的前綴和客戶端id的映射關系,因此我們也可以在客戶端指定需要接收失效消息的key前綴:
#telnet訪問redis客戶端(略)
#開啟RESP3
hello 3
#開啟廣播模式的客戶端緩存tracking,默認會收到所有的key的失效信息
client tracking on bcast
#開啟廣播模式的客戶端緩存tracking,只接受指定前綴'wyk'的key的失效信息
client tracking on bcast prefix wyk
廣播模式下,只要符合客戶端設置的key前綴的key發生新增、修改、刪除、過期、淘汰等動作,即使該key沒有被該客戶端緩存,也會收到key的失效消息;
重定向模式
為了兼容RESP2協議,在Redis6中客戶端緩存可以以重定向(Redirect)的方式實現,不再使用RESP3原生支持的PUSH消息,而是將消息通過Pub/Sub通知給另外一個客戶端連接:
#查看客戶端id
client id
#用于接收失效消息的客戶端訂閱頻道
subscribe _redis_:invalidate
#客戶端開啟Tracking客戶端緩存 并指定需要接收失效消息的客戶端ID
client tracking on bcast redirect receive_client_id
OPTIN和OPTOUT
在默認模式或重定向模式下,我們可以有選擇的對需要的key進行緩存,而由于廣播模式是匹配key前綴,因此不能使用此命令。
#RESP3 默認模式
#切換RESP3協議
hello 3
#開啟客戶端緩存optin選項
client tracking on optin
#此命令后面第一個只讀key會被緩存
client caching yes
#RESP2 重定向模式
hello 2
#開啟客戶端緩存optin選項,1234是接收失效消息的客戶端id
client tracking on REDIRECT 1234 OPTIN
#此命令后面第一個只讀key會被緩存
client caching yes
OPTIN:只有執行client caching yes之后的第一個key才會被緩存;
OPTOUT:與OPTIN相反,執行client caching on之后的第一個只讀key不會被緩存;
注意:在redis6.0.3版本中optin和optout選項時靈時不靈,可能還有BUG;
NOLOOP選項
我們的客戶端修改自己已緩存的key的時候也會收到這個key的過期信息,事實上這個客戶端是不需要收到該消息的,這造成了浪費,因此我們可以使用NOLOOP選項將該客戶端設置為:本客戶端修改的key不會收到相關的失效信息。
#開啟客戶端緩存的NOLOOP選項
client tracking on noloop
開啟noloop選項的客戶端,如果在該客戶端上修改它已經緩存的key,自己不會收到該key的失效消息:
沒開啟noloop選項的客戶端,如果在該客戶端上修改它已經緩存的key,自己也會收到該key的失效消息:
失效表key上限
可以使用?tracking_table_max_keys參數修改服務端失效表內記錄的緩存的key的數量,當失效表內記錄的緩存key達到配置的數量時會隨機從失效表內移除緩存:
#查詢最大緩存的數量
config get tracking-table-max-keys
#設置最大緩存數量為300
config set tracking-table-max-keys 300
參考文章:
Redis server-assisted client side caching?
Why RESP3 will be the only protocol supported by Redis 6
Redis客戶端緩存設計(In-Process caching)
帶你100% 地了解 Redis 6.0 的客戶端緩存
?
希望本文對你有幫助,請點個贊鼓勵一下作者吧~ 謝謝!
總結
以上是生活随笔為你收集整理的Redis系列(十四)、Redis6新特性之RESP3与客户端缓存(Client side caching)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高并发之--Guava Cache
- 下一篇: 渗透测试技巧之Redis漏洞利用总结