來源:urlify.cn/mYVVNfredis
Redis 6.0的新特性也是在一步步的討論和優化中肯定的。不少的特性已經在以前的RC等版本中介紹過了。可是正式GA版中也有一些新的變化:數據庫
@antirez 提到只是Redis歷史上最大的一次版本更新,因此謹慎建議在應用的產品中仍是多多測試評估,而且承諾一旦遇到大的bug就會緊急發佈6.0.1版。果不其然,一天後就發佈了 6.0.1版,修復了一個allocator的bug,這個bug是爲了優化而引入的,如今暫時去掉了。緩存
I just released Redis 6.0.1. Unfortunately there was a bug in Redis 6.0.0 introduced just a few days before the release, that only happens when using the non-default allocator (libc malloc in this case triggers it). Optimization reverted, 6.0.1 released. Sorry for the issue.
本文主要關注Client side caching(客戶端緩存)這一特性。app
smallnest/RESP3 是Redis RESP3協議的解析庫,你可使用它和Redis底層通信,或者包裝它實現新版的Redis client庫或者Redis Server端。
一年前,當 @antirez 參加完紐約Redis大會後,5:30就在旅店中醒來了,面對曼哈頓街頭的美麗景色,在芸芸衆生中思索Redis的將來。包括客戶端緩存。less
其實,客戶端緩存特性是收到Redis Conf 2018的Ben Malec的影響,一會兒打開了 @antirez 思路。咱們知道, 不少公司使用Redis作緩存系統,而且很好的提升了數據訪問的性能,可是不少企業爲了進一步應對熱點數據,仍是會在redis的client端緩存一部分熱點數據,用來應對吃瓜事件。好比在微博咱們常常遇到的是明星出軌、明星分分合合、突發事件等等,每一年都會有幾回突發的事件,微博除了使用Redis作緩存避免直接訪問數據庫,還會在前面加更多的cache層,好比L1 cache
等,採用memcached等產品做爲熱數據的緩存。那麼就有一個問題,如何可以及時的同步這些cache和redis的數據呢?Ben提供了很是有意思的想法。ide
佇立在曼哈頓的街頭,@antirez 陷入了沉思,後來回到旅館他開始實現第一版的客戶端的緩存。固然,最終Redis 6.0中實現和這個第一版的實現差異很大,可是非常顯然,從客戶端的演化過程當中咱們仍是能看到@antirez對這個特性所在的權衡(trade off)。關於這個歷史本文不作太多的介紹,由於咱們更關注於這個特性最終是什麼樣子的。memcached
Redis實現的是一個服務端協助的客戶端緩存,叫作tracking
。客戶端緩存的命令是:oop
CLIENT TRACKING ON|OFF [REDIRECT client-id] [PREFIX prefix] [BCAST] [OPTIN] [OPTOUT] [NOLOOP]
當tracking
開啓時, Redis會"記住"每一個客戶端請求的key,當key的值發現變化時會發送失效信息給客戶端(invalidation message)。失效信息能夠經過RESP3協議發送給請求的客戶端,或者轉發給一個不一樣的鏈接(支持RESP2+ Pub/Sub)。當廣播模式(broadcasting)開啓時,參與tracking
的客戶端會收到它經過前綴訂閱的key的相關的通知,即便它沒請求過對應的key。同時還提供了OPTIN
、OPTOUT
等模式。性能
失效消息:當一個key的數據有修改的時候,須要告訴客戶端它之前緩存的數據失效了,這時redis會主動發送一條失效消息
tracking
。在這種模式下客戶端須要設置將track的key的前綴,這些key的失效消息會廣播給全部參與的客戶端,無論這些客戶端是否請求/緩存額這些key。不開始廣播模式時,Redis只會track那些只讀命令請求的key,而且只會報告一次失效消息。CLIENT CACHING yes
以後被調用。CLIENT CACHING off
以後被調用。下面讓咱們一一介紹每一個選項。測試
首先讓咱們介紹RESP3協議相關的選項,REDIRECT <id>
放在最後介紹。
在嘗試以前,你首先須要安裝一個redis 6.x的版本,目前時6.0.1。在官方網站上有源代碼的下載,編譯安裝也很簡單:
make distclean make make test sudo make install
相信很快就有編譯好的二進制包能夠下載。
啓動server, 它會在6379端口啓動一個服務:
redis-server
使用redis-cli
訪問,默認訪問本機的6379實例:
redis-cli
固然你能夠經過-h
查看額外的參數配置,好比使用其它端口等等,這裏咱們使用最簡單的例子,重點是瞭解客戶端緩存的特性。
有時候爲了更好的觀察redis的返回結果,咱們使用telnet
而不是redis-cli
做爲client鏈接redis,由於redis-cli對結果作了處理,尤爲是失效消息,你可能沒法觀測到。
client tracking on
)啓動redis server:
啓動redis-cli:
固然,咱們使用telnet來測試,方便觀察redis的返回結果,剛纔redis-cli用來更新key值,輔助測試。鏈接上以後發送hello 3
開啓RESP3協議:
➜ ~ telnet localhost 6379 Trying ::1... Connected to localhost. Escape character is '^]'. hello 3 %7 $6 server $5 redis $7 version $5 6.0.1 ......
以後嘗試開啓tracking
並讀取a
的值:
client tracking on +OK set a 1 +OK get a $1 1
這個時候若是使用redis-cli做爲另一個client更新a
的值,telnet這個client應該能得到通知:
127.0.0.1:6379> set a 2 OK
觀察telnet,它收到了一個失效消息:
>2 $10 invalidate *1 $1 a
注意它採用RESP3中的PUSH類型(>
)。
若是這個使用你再使用redis-cli更新a
的值,telnet不會再收到失效消息。除非telnet client再get a
一次,從新tracking
a的值。
能夠隨時取消tracking
:
client tracking off
client tracking on
)上面的方式會tracking全部的key,若是你只想跟蹤特定的key, 目前redis提供了一種方式,也就是前綴匹配的方式。你能夠只tracking特定前綴的key。它值應用了廣播模式。
使用telnet client設定前綴和開啓tracking:
hello 3....... client tracking on prefix a bcast +OK client tracking on prefix user bcast +OK
咱們tracking兩個前綴,以a
開頭的全部的key和以user
開頭的全部的key,全部a
開頭的全部的key和以user
開頭的全部的key(包括a
和user
)的key變更時它應該都收到消息。
而後咱們使用redis-cli更新三個key: abc
、user:32432723213
和feed:6532343243432
:
127.0.0.1:6379> set abc 100 OK 127.0.0.1:6379> set user:32432723213 good OK 127.0.0.1:6379> set feed:6532343243432 abc OK
telnet client收到abc
和user:32432723213
的失效消息,而不會收到feed:6532343243432
的失效消息:
>2 $10 invalidate *1 $3 abc>2 $10 invalidate *1 $16 user:32432723213
你能夠經過client tracking off
中止客戶端緩存。目前貌似不能只中止對單個的前綴的tracking
。即便你使用client tracking off prefix user
也是取消對全部的key的tracking
。
...... } else if (!strcasecmp(c->argv[2]->ptr,"off")) { disableTracking(c); } else { ......
若是使用OPTIN
,能夠有選擇的開啓tracking
。只有你發送client caching yes
以後的下一條的只讀命令的key纔會tracking
, 不然其它的只讀命令中的key不會tracking。
首先咱們開始optin
,讀取a的指,這個時候使用redis-cli client修改a的值爲1000,咱們並無收到a
的失效消息。
client tracking on optin +OK get a $1 2
接下來咱們發送client caching yes
,緊接着獲取a的值,這個時候若是再修改a的值,你就能夠收到一條a的失效消息:
client caching yes +OK get a $4 1000 >2 $10 invalidate *1 $1 a
必須是緊跟着client caching yes
嗎?是的,好比發送下面的命令,只會tracking
b,而不是a:
client caching yes +OK get b _ get a $4 2000
若是使用OPTOUT
,你也能夠有選擇的退出tracking
。只有你發送client caching off
以後的下一條的只讀命令的key纔會中止tracking
, 不然其它的只讀命令中的key都會被tracking。
能夠看到它和OPTIN
正好相反,你能夠根據你的場景來選擇。
好比下面的例子,開啓OPTOUT
以後,對任意的key的變更都收到失效消息:
client tracking on optout +OK get a $4 3000 >2 $10 invalidate *1 $1 a
這個時候若是咱們想排除b
這個key,能夠只針對它進行設置:
client caching no +OK get b $1 3
以後對b的變更並不會收到b的失效消息。
注意: OPTIN
和OPTOUT
是針對的非BCAST場景,也就是隻有你發送了key的只讀命令後,纔會跟蹤相應的key。而廣播模式是不管你是否發送過key的只讀命令,只要redis修改了key,都會發送相應key(或者匹配前綴的key)的失效消息。
正常設置時,失效消息是發給全部參與的client,可是若是設置了NOLOOP
,則不會發送給更新這個key的client。
client tracking on bcast noloop +OK set a 1 +OK client tracking off +OK client tracking on bcast +OK set a 1 +OK >2 $10 invalidate *1 $1 a
注意,取消tracking只需調用client tracking off
便可。
最後,讓咱們看一下轉發消息的處理。這是爲了兼容RESP2協議一個處理方式,將失效消息轉發給另一個client。
首先咱們查看redis-cli的client id:
127.0.0.1:6379> client list id=4 addr=127.0.0.1:61017 fd=8 name= age=33103 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client user=default
使用telnet鏈接redis,查看client id:
client id :12
telnet 客戶端開啓訂閱失效消息:
SUBSCRIBE __redis__:invalidate *3 $9 subscribe $20 __redis__:invalidate :1
而後咱們就能夠將redis-cli的失效消息轉發給telnet client:
client tracking on bcast redirect 12 127.0.0.1:6379> set a 1000 OK
能夠看到telnet客戶端收到了失效消息:
*3 $7 message $20 __redis__:invalidate *1 $1 a
若是你要轉發的目的client開啓了RESP3協議,你就不須要RESP3 Pub/Sub了,由於RESP3原生支持Push消息。
redis的tracking feature的實現代碼在:tracking.c。