Redis命令介紹之位操作以及STRALGO命令

在前文中我們已經介紹了Redis中有關字符串的大部分命令。在本文中,我們將介紹一下Redis中位操作相關的命令,並簡單介紹6.0版本中新增的STRALGO命令。若需要了解其他的字符串命令,可參考之前的文章:

SETBIT

SETBIT命令用於設置指定偏移位的二進制值,設置的值必須爲01

SETBIT key offset value

使用SETBIT命令時,偏移量的值必須大於等於0,且小於4294967296(2^32)。若偏移量大於原字符串的長度,則該字符串將增長至能存放偏移量的長度,增長的部分將使用0填充。

示例

redis> SETBIT mykey 7 1
(integer) 0
redis> GET mykey
"\x01"
redis> SETBIT mykey 7 0
(integer) 1
redis> GET mykey
"\x00"

當偏移量大於字符串長度時,字符串將增長:

redis> SET greeting "hello world"
OK
redis> SETBIT greeting 94 1
(integer) 0
redis> GET greeting
"hello world\x02"

GETBIT

GETBIT命令用於返回指定指定偏移量的二進制值。

GETBIT key offset

使用GETBIT命令時若指定的偏移量大於字符串的長度,將認定超出的部分爲連續的0。當鍵值對不存在時,將認定其爲一個空白的字符串,即偏移量大於字符串的長度。與SETBIT命令不同的是,偏移量超出字符串時不會使字符串增長。

示例

redis> SETBIT mykey 7 1
(integer) 0
redis> GETBIT mykey 7
(integer) 1
redis> SET greeting "hello world"
OK
# 字符h的二進制爲01101000H
redis> GETBIT greeting 0
(integer) 0
redis> GETBIT greeting 1
(integer) 1
# greeting的長度爲88位,獲取超出字符串的長度的位
redis> GETBIT greeting 88
(integer) 0

BITCOUNT

BITCOUNT命令用於獲取指定範圍內字符串中二進制值爲1的位數。默認情況下計數範圍爲整個字符串,另外也可手動指定計數開始和結束的位置。不同於上文中介紹的SETBIT以及GETBIT命令,BITCOUNT參數中的偏移量單位爲字節而非位。

BITCOUNT key [start end]

與前文中介紹過的GETRANGE命令相似,也可以使用負數表示相對於字符串末尾的位置。

示例

redis> SET greeting "hello world"
OK
# 字符h的二進制爲01101000
redis> BITCOUNT greeting 0 0
(integer) 3
# 字符e的二進制爲01100101
redis> BITCOUNT greeting 1 1
(integer) 4
# 字符l的二進制爲01101100
# 字符d的二進制爲01100100
redis> BITCOUNT greeting -2 -1
(integer) 7
redis> BITCOUNT greeting
(integer) 45
# 偏移量end小於start的情況,相當於空字符串
redis> BITCOUNT greeting 3 1
(integer) 0

BITPOS

BITPOS命令用於獲取在指定範圍中首個二進制值爲01的位置。當鍵值對不存在時,將認爲是一個空字符串進行搜索。與BITCOUNT命令相同,BITPOS命令也可以以字節爲單位指定偏移量,使用負數值表示相對於字符串末尾的位置。

BITPOS key bit [start] [end]

使用BITPOS命令時,將認定超出字符串長度的部分爲連續的0

返回值

BITPOS命令將返回首個符合條件的二進制值的位置。如當字符串值爲"\xfd"時(即二進制值11111101),使用命令BITPOS key 1將得到結果爲0,使用命令BITPOS key 0將得到結果爲6。

當查找的值爲二進制值1,且字符串爲空或不包含1時,將返回-1

當查找的值爲二進制值0,字符串不爲空且只包含有1時,將返回字符串後的第一個位的位置。如當字符串值爲"\xff"時(即二進制值11111111),使用BITPOS key 0命令得到的結果爲8。

當同時設置偏移量start以及end時,將只會在指定範圍內查找。如當字符串值爲"\xff"時(即二進制值11111111),使用BITPOS key 0 0 0命令得到的結果爲-1。

示例

# 11111111 11111101
redis> SET mykey "\xff\xfd"
OK
redis> BITPOS mykey 1
(integer) 0
redis> BITPOS mykey 0
(integer) 14
# 在第一個字節中尋找
redis> BITPOS mykey 0 0 0
(integer) -1

BITOP

BITOP命令用於對多個值(除NOT操作外)執行位運算操作,並將結果保存至指定的鍵值對中。BITOP命令將返回結果字符串的長度,其值等於輸入中最長字符串的長度。

BITOP operation destkey key [key ...]

BITOP命令支持與(AND)、或(OR)、異或(XOR)以及非(NOT)四個位運算操作,其使用方式爲:

  • AND 與操作,使用方式爲BITOP AND destkey srckey1 srckey2 ...
  • OR 或操作,使用方式爲BITOP OR destkey srckey1 srckey2 ...
  • XOR 異或操作,使用方式爲BITOP XOR destkey srckey1 srckey2 ...
  • NOT 非操作,使用方式爲BITOP NOT destkey srckey

當輸入的字符串長度不同時,將使用0填充至與最長長度相同。若輸入的鍵不存在則認定爲一個空白字符串,並以0填充至與最長長度相同。

示例

在下面的示例中,我們將使用到下面幾個值作爲演示的源值:

# 10101010
redis> SET key1 "\xaa"
OK
# 01010101
redis> SET key2 "\x55"
OK
# 11110000
redis> SET key3 "\xf0"
OK
# 01010101 01010101
redis> SET key4 "\x5555"
OK

與(AND)操作:

# 10101010 & 01010101 = 00000000
redis> BITOP AND result key1 key2
(integer) 1
redis> GET result
"\x00"

或(OR)操作:

# 10101010 | 01010101 = 11111111
redis> BITOP OR result key1 key2
(integer) 1
redis> GET result
"\xff"

異或(XOR)操作:

# 10101010 ^ 11110000 = 01011010
redis> BITOP XOR result key1 key3
(integer) 1
# 字符Z二進制值爲 01011010
redis> GET result
"Z"

或(OR)操作:

# !10101010 = 01010101
redis> BITOP NOT result key1
(integer) 1
# 字符U二進制值爲 01010101
redis> GET result
"U"

不同長度的字符串進行位運算:

# key1的值將以0填充爲 10101010 00000000
# 10101010 00000000 | 01010101 01010101 = 11111111 00000000
redis> BITOP OR result key1 key4
(integer) 2
redis> GET result
"\xffU"

BITFIELD

使用BITFIELD將字符串看成二進制位數組,並對其中存儲不同長度的整數進行操作。例如設置偏移量爲1234的5位有符號整數的值,或是獲取偏移量爲4567的31位無符號整數的值。同時,BITFIELD命令也提供了INCRBY子命令對值進行加/減操作,並提供了設置以處理溢出的情況。

BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]

BITFIELD命令可通過傳遞多個命令對多個位域進行操作,並以數組的形式返回各命令執行的結果。例如下面的示例中,對mykey鍵中偏移量爲100的5位有符號整數進行自增量爲1的自增操作,並獲取偏移量爲0的4位無符號整數的值:

redis> BITFIELD mykey INCRBY i5 100 1 GET u4 0
1) (integer) 1
2) (integer) 0

BITFIELD命令提供了下列支持的子命令:

  • GET <type> <offset> 返回指定位域的值,若超出字符串的長度,超出部分將爲0。
  • SET <type> <offset> <value> 設置指定位域的值,並返回舊值。若超出字符串的長度,超出部分將以0填充。
  • INCRBY <type> <offset> <increment> 對指定位域的值進行自增操作(通過使用負的自增值進行減法的操作),並返回最新的值。若超出字符串的長度,超出部分將以0填充。

另外,BITFIELD命令還支持OVERFLOW子命令,用於設置發生溢出時執行的操作。

OVERFLOW [WRAP|SAT|FAIL]

OVERFLOW命令具有下列三個行爲的設置,在未顯式聲明的情況下,默認的溢出行爲爲WRAP

  • WRAP 環繞(wrap around)模式,也就是C語言中的標準行爲。即當上溢出時將從該類型最小的值開始計算,下溢出時從該類型最大的值開始計算。例如對值爲-128的8位有符號整數做減一的操作,將得到127。
  • SAT 發生溢出時將保持數值爲該類型的邊界值。如對值爲120的8位有符號整數做加10的操作將得到127,在後續繼續做加法操作值仍將保持在127。
  • FAIL 若將發生溢出,則將不執行INCRBY操作,並返回nil

對於BITFIELD命令中的<type>參數,需要傳遞位域的類型及大小。位域支持有符號整數和無符號整數兩種類型,分別使用符號i以及u表示。在類型符號後,需要聲明位域的大小,例如i32代表32位有符號整數,u15代表15位無符號整數。由於Redis的協議原因,位域支持的最大大小分別爲64位有符號整數及63位無符號整數。

BITFIELD命令提供了兩種方式設置偏移量:

  1. 即直接使用不帶前綴的數值,它表示以0開始從字符串起始位置計算偏移量,例如200表示字符串中的第201位。
  2. #作爲前綴的數值,它將與類型的長度相乘計算出實際的偏移量。例如對於命令BITFIELD mystring SET i8 #0 100 SET i8 #1 200,兩個子命令的實際偏移量分別爲0和8。

示例

# 01111111
redis> BITFIELD mykey SET i8 0 127
1) (integer) 0
# 5位有符號整形中,二進制值11111表示-1
# 5位無符號整形中,二進制值11111表示31
redis> BITFIELD mykey GET i5 3 GET u5 3
1) (integer) -1
2) (integer) 31
redis> BITFIELD mykey INCRBY u8 0 10 INCRBY i8 0 -15
1) (integer) 137
2) (integer) 122

通過OVERFLOW控制溢出的情況:

redis> BITFIELD overflow-test SET i8 0 120
(integer) 0
# 使用FAIL使發生溢出時不執行操作
redis> BITFIELD overflow-test OVERFLOW FAIL INCRBY i8 0 10
1) (nil)
# 使用SAT使發生溢出時保持在邊界值
redis> BITFIELD overflow-test OVERFLOW SAT INCRBY i8 0 10
1) (integer) 127
# 使用WRAP使發生溢出時值按環繞模式改變
redis> BITFIELD overflow-test OVERFLOW WRAP INCRBY i8 0 1
1) (integer) -128

結束語

STRALGO命令是6.0版本新增加的命令,用於執行一些複雜的字符串操作算法。STRALGO可能可以被用於DNA以及RNA序列的分析中。在本文中我們僅對STRALGO命令進行簡單的介紹。

STRALGO algorithm argument [argument ...]

在當前最新版本中(6.0.5),僅支持了LCS算法(longest common substring,最長公共子串),其使用方式爲:

STRALGO LCS [KEYS ...] [STRINGS ...] [LEN] [IDX] [MINMATCHLEN <len>] [WITHMATCHLEN]

以下爲STRALGO命令使用的示例:

redis> STRALGO LCS STRINGS salvatore sanfilippo
"salo"

關於STRALGO命令更多的使用方法,可以參考Redis文檔中的STRALGO頁面

至此,我們已經介紹了Redis中字符串相關所有命令,在接下去的文章中,我們將繼續介紹Redis中的其他類型命令。若需要對了解關於字符串命令的更多內容,可以參考Redis文檔中的字符串相關命令文檔

歡迎大家關注我的公衆號“風紙”,或是掃下面的二維碼關注👇
風紙

參考文獻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章