Redis學習手冊10—數據庫操作

前言

前面的章節中,我們介紹了Redis提供的一系列數據結構及其相關的命令。Redis作爲一款優秀的內存數據庫,因此也提供了一系列關於數據庫管理方面的操作命令,因此本章主要內容就是關於Redis數據庫管理方面的操作介紹。

主要內容

Redis爲數據庫提供了豐富的操作命令,通過這些命令,用戶可以:

  • 指定自己想要使用的數據庫
  • 一次性獲取數據庫包含的所有鍵,迭代地獲取數據庫包含的所有鍵,或者隨機地獲取數據庫中的某個鍵
  • 根據給定的鍵的值進行排序
  • 檢查給定的一個或多個鍵,看他們是否存在於數據庫中
  • 查看給定的鍵的類型
  • 對給定鍵進行重命名
  • 移除指定的鍵,或者將它從一個數據庫移動到另一個數據庫
  • 清空數據庫包含的所有鍵
  • 交換給定的兩個數據庫

命令速查表

下標列出了Redis數據庫操作命令速查表:

命令 用法及參數 說明
SELECT SELECT index 用於切換數據庫
KEYS KEYS pattern 獲取所有與給定模式匹配的鍵
SCAN SCAN cursor [MATCH pattern] [COUNT number] 以漸進方式獲取數據庫鍵, MATCH可選項用於匹配全局匹配符
COUNT選項可以指定迭代返回鍵的期望數量
HSCAN HSCAN hash cursor [MATCH pattern] [COUNT number] 可以以漸進的方式迭代給定的散列包含的鍵值對,與SCAN命令用法類似
SSCAN SSCAN set cursor [MATCH pattern] [COUNT number] 可以以漸進的方式迭代集合的元素,與SCAN命令類似
ZSCAN ZSCAN sorted_set cursor [MATCH pattern] [COUNT number] 可以以漸進的方式迭代有序集合的成員和分值,與SCAN命令類似
RANDOMKEY RANDOMKEY 隨機返回一個鍵
SORT SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] 對鍵的值進行排序
EXISTS EXISTS key [key ... ] 檢測一個或多個鍵是否存在於當前使用的數據庫中
DBSIZE DBSIZE 獲取當前使用的數據庫中有多少個鍵值對
RENAME RENAME origin new 修改鍵的名稱
RENAMENX RENAMENX origin new 只在新鍵名未被佔用時修改名稱
MOVE MOVE key db 將一個鍵從當前數據庫移動到目標數據庫
DEL DEL key [key ... ] 從當前正在使用的數據庫中移除一個或多個指定的鍵,以及它們的值
UNLINK UNLINK key [key ... ] 異步方式移除鍵
FLUSHDB FLUSHDB [async] 清空當前正在使用的數據庫
FLUSHALL FLUSHALL [async] 清空所有數據庫
SWAPDB SWAPDB x y 交換數據庫

命令詳解

SELECT:切換至指定的數據庫

一個Redis服務器可以包含多個數據庫。在默認情況下,Redis服務器在啓動的時候將會創建16個數據庫:這些數據庫使用號碼進行標識,其中第一個數據庫爲 0號數據庫,第二個爲 1號數據庫,依次類推。

SELECT index

Redis雖然不允許在同一個數據庫中使用兩個名稱相同的鍵,但是不同數據庫擁有不同的命名空間,所以不存在這個約束。

複雜度:O(1)O(1)
版本要求:Redis 1.0.0版本開始可用。

KEYS:獲取所有匹配的鍵

KEYS命令接受一個全局匹配符作爲參數,然後返回數據庫中所有與這個匹配符相匹配的鍵:

KEYS pattern

Redis支持的全局匹配符如下表所示:
在這裏插入圖片描述
複雜度:O(N)O(N)
版本要求:Redis 1.0.0版本開始可用。

SCAN:以漸進方式迭代數據庫鍵

因爲KYES命令需要檢查數據庫包含的所有鍵,並一次性的將符合條件的所有鍵返回給客戶端,所以當數據庫包含的鍵數量比較大的時候,使用KEYS命令可能會導致服務器被阻塞。

SCAN命令是一個迭代器,它每次被調用的時候都會從數據庫中獲取一部分鍵,用戶可以通過重複調用SCAN命令來迭代數據庫包含的所有鍵:

SCAN cursor

SCAN命令的執行結果由兩個元素組成:

  • 第一個元素是進行下一次迭代所需要的遊標,如果這個遊標爲0,說明已經完成了一次完整的迭代。
  • 第二個元素是一個列表,這個列表包含了本次迭代取得的數據庫鍵;如果SCAN命令在某次迭代中沒有獲取到任何鍵,那麼這個元素將是一個空列表。

關於SCAN命令返回的鍵列表,有兩點需要注意:

  • SCAN命令可能會返回重複的鍵,用戶如果不想再結果中包含重複的鍵,那麼就需要自己在客戶端進行檢測和過濾;
  • SCAN命令返回的鍵數量是不確定的,有時甚至會不返回任何鍵,但只要命令返回的遊標不爲0,迭代就沒有結束。

SCAN命令的迭代保證

針對數據庫的一次完整迭代以用戶給定遊標0調用SCAN命令開始,直到SCAN命令返回遊標0結束。SCAN命令爲完整迭代提供以下保證:

  • 從迭代開始到結束的整個過程中,一直存在於數據庫中的鍵總會被返回。
  • 如果一個鍵在迭代的過程中被添加到數據庫中,那麼這個鍵是否會被返回是不確定。
  • 如果一個鍵在迭代的過程中被移除了,那麼SCAN命令在它被移除之後將不再返回這個鍵,但是這個鍵在被移除之前還是會有可能被SCAN命令返回。
  • 無論數據庫如何變化,迭代總是有始有終的,不會出現循環迭代或者其他無法終止迭代的情況。
遊標的使用

在很多數據庫中,使用遊標都需要顯示的申請,並且在迭代完成之後釋放遊標,否則就會造成內存泄漏。與此相反,SCAN命令的遊標不需要申請,也不需要釋放,它們不佔用任何資源,每個客戶端都可以使用自己的遊標獨立地對數據庫進行迭代。
此外,用戶可以隨時在迭代的過程中停止迭代,或者隨時開始一次新的迭代,這不會浪費任何資源,也不會引發任何問題。

迭代與給定匹配符相匹配的鍵

在默認情況下,SCAN命令會向客戶端返回數據庫包含的所有鍵,就像 KEYS那樣。但是通過使用可選項 MATCH,同樣可以讓SCAN命令只返回與給定全局匹配符相匹配的鍵:

SCAN cursor [MATCH pattern]

指定返回鍵的期望數量

一般情況下,SCAN命令返回的鍵的數量是不確定的,但是我們可以使用可選項 COUNT 來指定一個期望值,以此來說明我們希望得到多少個鍵:

SCAN cursor [COUNT number]

特別注意:COUNT選項只是提供了一個期望值,告訴SCAN命令我們期望返回多少個鍵,但是每次迭代返回的數量仍然是不確定的。不過在通常情況下,設置一個較大的COUNT值將有助於獲得更多的鍵,這一點是可以肯定的。

數據結構迭代命令

與獲取數據庫鍵的 KYES命令一樣,Redis的各個數據結構也存在一些可能導致服務器阻塞的命令:

  • 散列的 HKEYS 命令、HVALS命令和HGETALL命令在處理鍵較多的情況下,可能會導致服務器阻塞。
  • 集合的 SMEMBERS命令在處理包含較多元素時,可能會導致服務器阻塞。
  • 有序集合的一些範圍型命令,比如 ZRANGE命令,也有可能導致服務器阻塞。

爲了解決以上問題,Redis爲散列、集合和有序集合也提供了一系列與SCAN命令類似的遊標迭代命令,分別是:HSCAN命令、SSCAN命令、ZSCAN命令。

散列迭代命令

HSCAN命令可以以漸近的方式迭代給定散列包含的鍵值對:

HSCAN hash cursor [MATCH pattern] [COUNT number]

除了需要指定被迭代的散列之外,HSCAN命令的其他參數與SCAN命令的一樣,作用也一樣。當散列包含較多的鍵值對時,應該儘量使用 HSCAN命令代替 HKEYSHVALSHGETALL,以免造成服務器阻塞。

集合迭代命令

SSCAN 命令可以以漸進的方式迭代集合包含的元素:

SSCAN set cursor [MATCH pattern] [COUNT number]

SSCAN命令的參數與SCAN命令的一樣,作用也一樣。當集合包含較多的元素時,我們應該儘量使用SSCAN命令代替SMEMBERS命令,以免造成服務器阻塞。

有序集合迭代命令

ZSCAN命令可以以漸進的方式迭代給定的有序集合中的成員和分值:

ZSCAN sorted_set cursor [MATCH pattern] [COUNT number]

當有序集合中包含較多的成員時,應該儘量用 ZSCAN命令代替 ZRANGE命令以及其他可能會返回大量成員的範圍型命令,以免造成服務器阻塞。

RANDOMKEY:隨機返回一個鍵

RANDOMKEY命令可以從數據庫中隨機返回一個鍵:

RANDOMKEY

該命令不會移除被返回的鍵,它們會繼續留在數據庫中。

複雜度:O(1)O(1)
版本要求:Redis 1.0.0版本開始可用。

SORT:對鍵的值進行排序

用戶可以通過執行SORT命令對列表元素、集合元素或者有序集合成員進行排序。爲了讓用戶能夠以不同的方式進行排序,Redis爲SORT命令提供了非常多的可選項,如果我們以不給定任何可選項的方式執行SORT命令,那麼命令將會對指定鍵的值按數字值進行排序:

SORT key

在默認情況下,SORT命令將按照從小到大的順序返回排序後的各個值。

指定排序方式

默認情況下,SORT命令會按照升序的方式進行排序。通過使用可選項 ASC 或者 DESC,可以來指定排序的方式:

SORT key [ASC | DESC]

ASC表示升序也是默認的方式,DESC表示降序。

對字符串值進行排序

SORT命令默認情況下進行的都是數字值的排序,如果我們嘗試直接去對字符串進行排序,將會引發錯誤:

127.0.0.1:6379> SORT fruits
(error) ERR One or more scores can't be converted into double

如果要對字符串進行排序,那麼需要使用可選項 ALPHA 來實現:

SORT key [ALPHA]

只獲取部分排序結果

默認情況下,SORT命令將返回排序後的全部元素,如果只想獲取部分排序結果,那麼可以使用可選項 LIMIT

SORT key fruits [LIMIT offset count]

其中 offset參數用於指定返回結果之前需要跳過的元素數量,而count參數則用於指定需要獲取的元素數量。

獲取外部鍵的值作爲結果

在默認情況下,SORT命令將返回被排序後的元素作爲結果,但如果用戶想要獲取其他值作爲排序結果,可以使用可選項 GET 來實現:

SORT key [[GET pattern] [GET pattern] ... ]

一個SORT命令可以使用任意多個GET pattern選項,其中pattern參數的值可以是:

  • 包含 * 符號的字符串;
  • 包含 * 符號和 **->**符號的字符串;
  • 一個單獨的 # 符號。

獲取字符串鍵的值

pattern參數的值是一個包含 * 符號的字符串時,SORT命令將把被排序的元素與 * 符號進行替換,構建出一個鍵名,然後使用 GET命令去獲取該鍵的值:

字符串鍵
“apple-price” 8.5
“banana-price” 4.5
cherry-price" 7

上述表格是用來表示水果價格的字符串類型鍵值對,下面用SORT命令對水果集合進行排序,然後根據排序後的結果獲取對應水果的價格:

127.0.0.1:6379> SORT fruits ALPHA GET *-price
1) "8.5"
2) "4.5"
3) "7"

這個SORT命令的執行過程可分爲以下三個步驟:

1)對fruits集合的各個元素進行排序,得出一個由 “apple”、“banana”、"cherry"組成的有序元素列表。
2)將排序後的各個元素與 *-price模式進行匹配和替換,得出鍵名:“apple-price”、“banana-price”、“cherry-price”
3)使用GET命令獲取上述步驟得到的鍵名對應的值,並依次返回這些值。

獲取散列中的鍵值

pattern參數的值是一個包含 * 符號 和 -> 符號的字符串時,SORT命令將使用 -> 左邊的字符串爲散列名,-> 右邊的字符串爲字段名,調用 HGET命令,從散列中獲取指定字段的值,此外,用戶傳入的散列名還需要包含 * 符號,這個 * 符號將被替換成被排序的元素。

散列名 散列中的inventory字段的值
“apple-info” “1000”
“banana-info” “300”
“cherry-info” “50”
127.0.0.1:6379> SORT fruits ALPHA GET *-info->inventory
1) "1000"
2) "300"
3) "50"

獲取被排序元素本身

pattern參數的值是一個 # 符號時,SORT命令將返回被排序的元素本身。因爲SORT key命令和**SORT key GET #**命令返回的結果完全相同,所以單獨使用沒有實際作用。

使用外部鍵的值作爲排序權重

在默認情況下,SORT命令將使用被排序元素本身作爲排序權重,但在有需要的情況下,可以使用可選項 BY 指定其他鍵的值作爲排序的權重:

SORT key [BY pattern]

pattern的值與 可選項 GET的一樣。

保存排序結果

在默認情況下,SORT命令會將排序結果直接返回給客戶端,但是如果有需要,也可以將排序結果保存到指定的鍵中:

SORT key [STORE destination]

如果用戶給定的destination鍵已經存在,那麼SORT命令會先移除該鍵,然後再存儲排序的結果。

平均複雜度:O(Nlog(N)+M)O(N*log(N)+M),其中NN爲被排序元素的數量,而MM爲命令返回的元素的數量。
版本要求:Redis 1.0.0版本開始可用。

EXISTS:檢查給定的鍵是否存在

用戶可以通過EXISTS命令檢查給定的一個或多個鍵是否存在於當前使用的數據庫中:

EXISTS key [key ... ]

EXISTS命令將返回存在的給定鍵數量作爲返回值。通過將多個鍵傳遞給EXISTS,可以判斷出給定的鍵中,有多少個存在。

EXISTS命令從Redis 3.0.3版本開始接受多個鍵作爲輸入,在此前的版本中,只能接受一個鍵作爲輸入。

DBSIZE:獲取數據庫包含的鍵值對數量

使用DBSIZE命令可以獲取當前使用的數據庫中有多少個鍵值對:

DBSIZE

TYPE:查看鍵的類型

TYPE命令允許我們查看給定鍵的類型:

TYPE key

下標列出了TYPE命令在面對不同類型的鍵時返回的各項結果:

鍵類型 TYPE命令返回值
字符串鍵 string
散列鍵 hash
列表鍵 list
集合鍵 set
有序集合鍵 zset
HyperLogLog string
位圖 string
地理位置 zset
stream
  • 因爲HyperLogLog和位圖這兩種鍵在底層都是通過字符串鍵來實現的,所以TYPE命令對於這兩種鍵將返回string作爲結果。
  • HyperLogLog和位圖的情況類似,因爲地理位置鍵使用了有序集合鍵作爲底層實現,所以返回 zset作爲結果。

複雜度:O(1)O(1)
版本要求:從Redis 1.0.0版本開始可用。

RENAME、RENAMENX:修改鍵名

Redis提供了RENAME命令來修改鍵的名稱:

RENAME origin new

如果用戶指定的新建名已經被佔用,那麼RENAME命令會先移除佔用了新鍵名的那個鍵,然後再執行改名操作。

除了RENAME之外,還提供了RENAMENX命令,該命令也可以修改鍵名,但是它只會在新鍵名未被佔用的情況下進行改名操作:

RENAMENX origin new

RENAMENX命令在改名成功時返回1,失敗時返回0

MOVE:將給定的鍵移動到另一個數據庫

用戶可以使用MOVE命令,將一個鍵從當前數據庫移動到目標數據庫:

MOVE key db

當移動成功時返回1,失敗返回0 ,當目標數據庫存在於給定鍵名相同的鍵時,MOVE命令將放棄移動操作。

DEL:刪除指定的鍵

使用DEL命令可以從當前正在使用的數據庫中移除指定的一個或多個鍵,以及這些鍵關聯的值:

DEL key [key ... ]

UNLINK:以異步方式移除指定的鍵

DEL命令實際上隱含着一個性能問題:因爲DEL命令會以同步的方式執行移除操作,所以如果待移除的鍵非常龐大或者數量較多,那麼服務器在執行移除操作的過程中可能會被阻塞。

爲了解決這個問題,Redis從4.0版本開始新增了一個UNLINK命令:

UNLINK key [key ... ]

UNLINK命令與DEL命令一樣,都可以移除指定的鍵,但是它是異步的方式去移除鍵:當用戶調用UNLINK命令時,它只會在數據庫中移除對該鍵的引用(Reference),而對鍵的實際移除操作則會交給後臺線程執行,因此不會造成服務器阻塞。

FLUSHDB:清空當前數據庫

使用FLUSHDB命令可以清空當前正在使用的數據庫:

FLUSHDB [async]

其中可選項 async 用於指定FLUSHDB是否開啓異步方式執行,默認情況下,FLUSHDB命令是以同步的方式執行的,這與 DEL命令一樣。

FLUSHALL:清空所有數據庫

使用FLUSHALL命令可以清空所有數據庫:

FLUSHALL [async]

其中可選項 async 用於指定FLUSHALL是否開啓異步方式執行,默認情況下,FLUSHALL命令是以同步的方式執行的,這與 DEL命令一樣。

SWAPDB:交換數據庫

SWAPDB命令接受兩個數據庫號碼作爲輸入,然後對指定的兩個數據庫進行互換,最後返回OK:

SWAPDB x y

SWAPDB命令執行成功後,原本存儲在數據庫 x 中的鍵值對將出現在 y 中,而原本在y中的鍵值對則出現在 x中。

上一篇:Redis學習手冊9—數據結構之流

下一篇:Redis學習手冊11—自動過期

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