1. Redis 6.0 除了多線程,別忘了這個(gè)牛逼特性!

        共 6534字,需瀏覽 14分鐘

         ·

        2020-07-28 12:08


        點(diǎn)擊上方“JAVA”,星標(biāo)公眾號(hào)
        重磅干貨,第一時(shí)間送達(dá)

        Redis 6.0的新特性也是在一步步的討論和優(yōu)化中確定的。

        很多的特性已經(jīng)在之前的RC等版本中介紹過(guò)了。

        但是正式GA版中也有一些新的變化:

        • SSL
        • ACL: 更好,命令支持
        • RESP3
        • Client side caching:重新設(shè)計(jì)
        • Threaded I/O
        • Diskless replication on replicas
        • Cluster support in Redis-benchmark and improved redis-cli cluster support
        • Disque in beta as a module of Redis: 開(kāi)始侵入消息隊(duì)列領(lǐng)域
        • Redis Cluster Proxy
        • 支持RDB不再使用時(shí)可立即刪除,針對(duì)不落盤(pán)的場(chǎng)景
        • PSYNC2: 優(yōu)化的復(fù)制協(xié)議
        • 超時(shí)設(shè)置支持更友好
        • 更快的RDB加載,20% ~ 30%的提升
        • STRALGO,新的字符串命令,目前只有一個(gè)實(shí)現(xiàn)LCS (longest common subsequence)

        @antirez 提到只是Redis歷史上最大的一次版本更新,所以謹(jǐn)慎建議在應(yīng)用的產(chǎn)品中還是多多測(cè)試評(píng)估,并且承諾一旦遇到大的bug就會(huì)緊急發(fā)布6.0.1版。果不其然,一天后就發(fā)布了 6.0.1版,修復(fù)了一個(gè)allocator的bug,這個(gè)bug是為了優(yōu)化而引入的,現(xiàn)在暫時(shí)去掉了。

        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.

        本文主要關(guān)注Client side caching(客戶端緩存)這一特性。

        smallnest/RESP3 是Redis RESP3協(xié)議的解析庫(kù),你可以使用它和Redis底層通訊,或者包裝它實(shí)現(xiàn)新版的Redis client庫(kù)或者Redis Server端。

        一年前,當(dāng) @antirez 參加完紐約Redis大會(huì)后,5:30就在旅店中醒來(lái)了,面對(duì)曼哈頓街頭的美麗景色,在蕓蕓眾生中思索Redis的未來(lái)。包括客戶端緩存。

        其實(shí),客戶端緩存特性是收到Redis Conf 2018的Ben Malec的影響,一下子打開(kāi)了 @antirez 思路。我們知道, 很多公司使用Redis做緩存系統(tǒng),并且很好的提高了數(shù)據(jù)訪問(wèn)的性能,但是很多企業(yè)為了進(jìn)一步應(yīng)對(duì)熱點(diǎn)數(shù)據(jù),還是會(huì)在redis的client端緩存一部分熱點(diǎn)數(shù)據(jù),用來(lái)應(yīng)對(duì)吃瓜事件。比如在微博我們經(jīng)常遇到的是明星出軌、明星分分合合、突發(fā)事件等等,每年都會(huì)有幾次突發(fā)的事件,微博除了使用Redis做緩存避免直接訪問(wèn)數(shù)據(jù)庫(kù),還會(huì)在前面加更多的cache層,比如L1 cache等,采用memcached等產(chǎn)品作為熱數(shù)據(jù)的緩存。那么就有一個(gè)問(wèn)題,如何能夠及時(shí)的同步這些cache和redis的數(shù)據(jù)呢?Ben提供了非常有意思的想法。

        佇立在曼哈頓的街頭,@antirez 陷入了沉思,后來(lái)回到旅館他開(kāi)始實(shí)現(xiàn)初版的客戶端的緩存。當(dāng)然,最終Redis 6.0中實(shí)現(xiàn)和這個(gè)初版的實(shí)現(xiàn)差別很大,但是很是顯然,從客戶端的演化過(guò)程中我們還是能看到@antirez對(duì)這個(gè)特性所在的權(quán)衡(trade off)。關(guān)于這個(gè)歷史本文不做太多的介紹,因?yàn)槲覀兏P(guān)注于這個(gè)特性最終是什么樣子的。

        Redis實(shí)現(xiàn)的是一個(gè)服務(wù)端協(xié)助的客戶端緩存,叫做tracking。客戶端緩存的命令是:

        CLIENT?TRACKING?ON|OFF?[REDIRECT?client-id]?[PREFIX?prefix]?[BCAST]?[OPTIN]?[OPTOUT]?[NOLOOP]

        當(dāng)tracking開(kāi)啟時(shí), Redis會(huì)"記住"每個(gè)客戶端請(qǐng)求的key,當(dāng)key的值發(fā)現(xiàn)變化時(shí)會(huì)發(fā)送失效信息給客戶端(invalidation message)。失效信息可以通過(guò)RESP3協(xié)議發(fā)送給請(qǐng)求的客戶端,或者轉(zhuǎn)發(fā)給一個(gè)不同的連接(支持RESP2+ Pub/Sub)。當(dāng)廣播模式(broadcasting)開(kāi)啟時(shí),參與tracking的客戶端會(huì)收到它通過(guò)前綴訂閱的key的相關(guān)的通知,即使它沒(méi)請(qǐng)求過(guò)對(duì)應(yīng)的key。同時(shí)還提供了OPTINOPTOUT等模式。

        失效消息:當(dāng)一個(gè)key的數(shù)據(jù)有修改的時(shí)候,需要告訴客戶端它以前緩存的數(shù)據(jù)失效了,這時(shí)redis會(huì)主動(dòng)發(fā)送一條失效消息

        • REDIRECT?: 將失效消息轉(zhuǎn)發(fā)給另外一個(gè)客戶端。當(dāng)我們不使用RESP3而是使用老的RESP2和Redis通訊時(shí),client本身不支持處理失效消息,所以可以開(kāi)啟一個(gè)支持Pub/Sub客戶端處理失效消息。當(dāng)然如果客戶端支持RESP3也可以將失效消息轉(zhuǎn)發(fā)給另外一個(gè)客戶端。這個(gè)cace我們放在最后演示。
        • BCAST: 使用廣播模式開(kāi)始tracking。在這種模式下客戶端需要設(shè)置將track的key的前綴,這些key的失效消息會(huì)廣播給所有參與的客戶端,不管這些客戶端是否請(qǐng)求/緩存額這些key。不開(kāi)始廣播模式時(shí),Redis只會(huì)track那些只讀命令請(qǐng)求的key,并且只會(huì)報(bào)告一次失效消息。
        • PREFIX?: 只應(yīng)用了廣播模式,注冊(cè)一個(gè)key的前綴。所有以這個(gè)前綴開(kāi)始的key有修改時(shí),都會(huì)發(fā)送失效消息??梢宰?cè)多個(gè)前綴。如果不設(shè)置前綴,那么廣播模式會(huì)track每一個(gè)key。
        • OPTIN: 當(dāng)廣播模式?jīng)]有激活時(shí),正常不會(huì)track只讀命令的key,除非它們?cè)?code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;">CLIENT CACHING yes之后被調(diào)用。
        • OPTOUT: 當(dāng)廣播模式?jīng)]有激活時(shí),正常會(huì)track只讀命令的key,除非它們?cè)?code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;font-size: 14px;border-radius: 4px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;">CLIENT CACHING off之后被調(diào)用。
        • NOLOOP: 不發(fā)送client自己修改的key。

        下面讓我們一一介紹每個(gè)選項(xiàng)。

        測(cè)試環(huán)境搭建

        首先讓我們介紹RESP3協(xié)議相關(guān)的選項(xiàng),REDIRECT 放在最后介紹。

        在嘗試之前,你首先需要安裝一個(gè)redis 6.x的版本,目前時(shí)6.0.1。在官方網(wǎng)站上有源代碼的下載,編譯安裝也很簡(jiǎn)單:

        make?distclean
        make
        make?test
        sudo?make?install

        相信很快就有編譯好的二進(jìn)制包可以下載。

        啟動(dòng)server, 它會(huì)在6379端口啟動(dòng)一個(gè)服務(wù):

        redis-server

        使用redis-cli訪問(wèn),默認(rèn)訪問(wèn)本機(jī)的6379實(shí)例:

        redis-cli

        當(dāng)然你可以通過(guò)-h查看額外的參數(shù)配置,比如使用其它端口等等,這里我們使用最簡(jiǎn)單的例子,重點(diǎn)是了解客戶端緩存的特性。

        有時(shí)候?yàn)榱烁玫挠^察redis的返回結(jié)果,我們使用telnet而不是redis-cli作為client連接redis,因?yàn)閞edis-cli對(duì)結(jié)果做了處理,尤其是失效消息,你可能無(wú)法觀測(cè)到。

        BCAST 廣播模式 (client tracking on)

        啟動(dòng)redis server:

        啟動(dòng)redis-cli:

        當(dāng)然,我們使用telnet來(lái)測(cè)試,方便觀察redis的返回結(jié)果,剛才redis-cli用來(lái)更新key值,輔助測(cè)試。連接上之后發(fā)送hello 3開(kāi)啟RESP3協(xié)議:

        ???~?telnet?localhost?6379
        Trying?::1...
        Connected?to?localhost.
        Escape?character?is?'^]'.
        hello?3
        %7
        $6
        server
        $5
        redis
        $7
        version
        $5
        6.0.1
        ......

        之后嘗試開(kāi)啟tracking并讀取a的值:

        client?tracking?on
        +OK
        set?a?1
        +OK
        get?a
        $1
        1

        這個(gè)時(shí)候如果使用redis-cli作為另外一個(gè)client更新a的值,telnet這個(gè)client應(yīng)該能獲得通知:

        127.0.0.1:6379>?set?a?2
        OK

        觀察telnet,它收到了一個(gè)失效消息:

        >2
        $10
        invalidate
        *1
        $1
        a

        注意它采用RESP3中的PUSH類(lèi)型(>)。

        如果這個(gè)使用你再使用redis-cli更新a的值,telnet不會(huì)再收到失效消息。除非telnet client再get a一次,重新tracking?a的值。

        可以隨時(shí)取消tracking:

        client?tracking?off

        tracking特定前綴的key (client tracking on)

        上面的方式會(huì)tracking所有的key,如果你只想跟蹤特定的key, 目前redis提供了一種方式,也就是前綴匹配的方式。你可以只tracking特定前綴的key。它值應(yīng)用了廣播模式。

        使用telnet client設(shè)定前綴和開(kāi)啟tracking:

        hello?3
        .......
        client?tracking?on?prefix?a?bcast
        +OK
        client?tracking?on?prefix?user?bcast
        +OK

        我們tracking兩個(gè)前綴,以a開(kāi)頭的所有的key和以user開(kāi)頭的所有的key,所有a開(kāi)頭的所有的key和以user開(kāi)頭的所有的key(包括auser)的key變動(dòng)時(shí)它應(yīng)該都收到消息。

        然后我們使用redis-cli更新三個(gè)key:?abc、user:32432723213feed: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收到abcuser:32432723213的失效消息,而不會(huì)收到feed:6532343243432的失效消息:

        >2
        $10
        invalidate
        *1
        $3
        abc
        >2
        $10
        invalidate
        *1
        $16
        user:32432723213

        你可以通過(guò)client tracking off停止客戶端緩存。目前貌似不能只停止對(duì)單個(gè)的前綴的tracking。即使你使用client tracking off prefix user也是取消對(duì)所有的key的tracking。

        ......
        }?else?if?(!strcasecmp(c->argv[2]->ptr,"off"))?{
        ????disableTracking(c);
        }?else?{
        ......

        選擇加入

        如果使用OPTIN,可以有選擇的開(kāi)啟tracking。只有你發(fā)送client caching yes之后的下一條的只讀命令的key才會(huì)tracking, 否則其它的只讀命令中的key不會(huì)tracking。

        首先我們開(kāi)始optin,讀取a的指,這個(gè)時(shí)候使用redis-cli client修改a的值為1000,我們并沒(méi)有收到a的失效消息。

        client?tracking?on?optin
        +OK
        get?a
        $1
        2

        接下來(lái)我們發(fā)送client caching yes,緊接著獲取a的值,這個(gè)時(shí)候如果再修改a的值,你就可以收到一條a的失效消息:

        client?caching?yes
        +OK
        get?a
        $4
        1000
        >2
        $10
        invalidate
        *1
        $1
        a

        必須是緊跟著client caching yes嗎?是的,比如發(fā)送下面的命令,只會(huì)tracking?b,而不是a:

        client?caching?yes
        +OK
        get?b
        _
        get?a
        $4
        2000

        選擇退出

        如果使用OPTOUT,你也可以有選擇的退出tracking。只有你發(fā)送client caching off之后的下一條的只讀命令的key才會(huì)停止tracking, 否則其它的只讀命令中的key都會(huì)被tracking。

        可以看到它和OPTIN正好相反,你可以根據(jù)你的場(chǎng)景來(lái)選擇。

        比如下面的例子,開(kāi)啟OPTOUT之后,對(duì)任意的key的變動(dòng)都收到失效消息:

        client?tracking?on?optout
        +OK
        get?a
        $4
        3000
        >2
        $10
        invalidate
        *1
        $1
        a

        這個(gè)時(shí)候如果我們想排除b這個(gè)key,可以只針對(duì)它進(jìn)行設(shè)置:

        client?caching?no
        +OK
        get?b
        $1
        3

        之后對(duì)b的變動(dòng)并不會(huì)收到b的失效消息。

        注意:?OPTINOPTOUT是針對(duì)的非BCAST場(chǎng)景,也就是只有你發(fā)送了key的只讀命令后,才會(huì)跟蹤相應(yīng)的key。而廣播模式是無(wú)論你是否發(fā)送過(guò)key的只讀命令,只要redis修改了key,都會(huì)發(fā)送相應(yīng)key(或者匹配前綴的key)的失效消息。

        NOLOOP

        正常設(shè)置時(shí),失效消息是發(fā)給所有參與的client,但是如果設(shè)置了NOLOOP,則不會(huì)發(fā)送給更新這個(gè)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只需調(diào)用client tracking off即可。

        REDIRECT

        最后,讓我們看一下轉(zhuǎn)發(fā)消息的處理。這是為了兼容RESP2協(xié)議一個(gè)處理方式,將失效消息轉(zhuǎn)發(fā)給另外一個(gè)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 客戶端開(kāi)啟訂閱失效消息:

        SUBSCRIBE?__redis__:invalidate
        *3
        $9
        subscribe
        $20
        __redis__:invalidate
        :1

        然后我們就可以將redis-cli的失效消息轉(zhuǎn)發(fā)給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

        如果你要轉(zhuǎn)發(fā)的目的client開(kāi)啟了RESP3協(xié)議,你就不需要RESP3 Pub/Sub了,因?yàn)镽ESP3原生支持Push消息。

        redis的tracking feature的實(shí)現(xiàn)代碼在:tracking.c。

        來(lái)源 |?https://urlify.cn/mYVVNf

        --END--


        ? 推薦

        公眾號(hào)ID|javabaiwen

        小編微信|619531440


        每天分享技術(shù)干貨

        視頻|電子書(shū)|面試題|開(kāi)發(fā)經(jīng)驗(yàn)

        瀏覽 42
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 国产免费黄色电影 | 中文字幕日韩精品亚洲一区小树林 | 国产成人精品免费视频 | 裸体动态图 | 欧美色图在线观看视频 |