當前位置:
首頁 > 最新 > 如何優雅地實現Redis命令setbits與getbits

如何優雅地實現Redis命令setbits與getbits

在之前的文章《如何優雅地使用Redis之點陣圖操作》和《再談如何優雅地使用Redis之點陣圖操作》中,筆者介紹了關於Redis點陣圖操作的高級應用,其中就講到了如何優雅地實現getbits。Redis官方提供了getbit命令,其可以獲取某個key對應比特位的比特值,而getbits顧名思義就是支持一次性獲取多個比特位的比特值的命令,遺憾的是,Redis官方並沒有提供getbits命令。在上述2篇文章中,筆者是通過解析位元組數組的方式來實現getbits命令的,雖然可以實現,但是卻有2個不足之處:1、這種方式實現的getbits命令不是原子性的,因為這種方式實現的getbits命令其實是分2步進行的,先讀取位元組數組,再解析位元組數組,在這2個步驟之間,Redis是可以執行其他命令的,所以可能會出現數據不一致的現象。2、當存儲的點陣圖數據空間佔用比較大時,一次性讀取整個位元組數組,會造成Redis伺服器阻塞,嚴重的還會造成客戶端內存溢出,雖然可以通過分多次去讀取位元組數組來避免這個問題,但是這樣一來就增加了網路開銷,不是特別優雅。

今天給大家介紹一種通過Redis原生命令bitfield實現setbits和getbits的方法。

bitfield命令

首先介紹一下bitfield命令的用途。官方對bitfield命令的介紹是:通過bitfield命令可以一次性操作多個比特位域,它會執行一系列操作並返回一個響應數組,這個數組中的元素對應參數列表中的相應操作的執行結果。說白了就是通過bitfield命令我們可以一次性對多個比特位域進行操作。需要注意的是,這裡提到的是比特位域,不是比特位,所謂比特位域,指的是連續的多個比特位,也就是說,bitfield不僅僅可以對多個單個的比特位進行操作,還支持對多個比特位域進行操作,所以功能是十分強大的。

這裡的操作指的是以下幾種:

GET

SET

INCRBY

其中,get命令的作用是讀取指定位域的值,set命令的作用是設置指定位域的值並返回舊的值,increby命令的作用是增加或減少指定位域的值並返回新的值。

舉個例子:

BITFIELD mykey SET i5 100 10 GET u4 2

這個命令包含了2個子操作,分別是SET i5 100 10和GET u4 2。SET i5 100 10的作用是從第100位開始,將接下來的5位用有符號數10代替,其中i表示的是有符號整數。GET u4 2的作用是從第2位開始,將接下來的4位當成無符號整數並取出,其中u表示的是無符號整數。

上述只是bitfield的一部分應用,實際上bitfield還有很多更高級的用法,有興趣的可以去Redis官網查閱,這裡就不再詳細介紹了。

實現setbits

接下來說下如果使用bitfield實現setbits原子命令。如果我們要將某一位(比如說第3位)設置為1,可以使用這樣的子操作:set u1 3 1,同樣地,如果我們需要將多個位設置成1,只要將多個set子操作拼接在一起可以了。舉個例子:如果我們要將第1位、第3位、第6位設置成1,則可以使用如下命令:

bitfield k1 set u1 1 1 set u1 3 1 set u1 6 1

其中k1指的是key。

我們可以寫個程序驗證下。驗證的方法是先使用上述命令對相應的比特位進行設值,然後使用redis原生的getbit命令遍歷每個比特位,看看是不是對應的位都可以被設置成1。

程序如下:

我們看下結果輸出:

可以看到,第1位、第3位、第6位都被設置成了true,而其他位還是原始值flase。所以這種方式確實可以實現一次性對多個比特位進行設值。

實現getbits

接下來我們使用bitfield命令來實現getbits原子命令。如果想讀取某個位(比如說第3位)的比特值,可以使用這樣的子操作:get u1 3。如果需要同時讀取多個比特位,則只需要將多個get子操作拼接在一起就可以了。還是舉個例子,如果我們想同時讀取第2位、第4位、第7位的比特值,可以使用如下命令:

bitfield k1 get u1 2 get u1 4 get u1 7

其中k1指的是key。

我們還是寫個程序驗證下。驗證的方式是使用Redis原生的setbit命令分別將第2位、第4位、第7位比特位設置成1,然後使用上述bitfield命令分別讀取每個比特位的值,看看是否只有對應的比特位被設置成了1。

程序如下:

結果輸出如下:

可以看到,第2位、第4位、第7位都被設置成了1,而其他位還是原始的值0。說明確實可以使用bitfield命令來實現getbits。

總結

使用bitfield實現getbits和setbits的好處有2個:1、原子性保證,由於所有操作都是在一個bitfield命令中完成的,所以可以保證操作的原子性。2、由於這種方式是在Redis服務端解析後再返回給客戶端的,客戶端並不需要一次性讀取整個位元組數組,所以不會造成客戶端內存溢出。

是不是很神奇?


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java架構沉思錄 的精彩文章:

知乎大V@Phodal:小白也能看懂的Web安全進階指南

TAG:Java架構沉思錄 |