➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
Java 測試(四):PowerMockcURL 基本操作

透過 Redis CLI 學習 Redis

Continued from previous post:
Spring 項目使用 Redis 做 caching

Table of contents

1 Redis 簡介

關於 Redis 既基本簡介可以喺呢篇度搵到:Spring 項目使用 Redis 做 caching - Redis 簡介

2 基本概念

Redis 有 16 個 databases(0-based,015),每個 database 裡面既數據都係以 key-value pair 既形式儲存。
Redis 既 data types 指既係 key-value pair 既 value 所用既儲存格式。

3 本地運行

關於點樣本地運行 Redis 可以喺呢篇度搵到:Spring 項目使用 Redis 做 caching - 安裝

4 Database 操作

4.1 選擇 database

Redis CLI 成功連接之後,初始選擇既係 database 0
SELECT "<database index, 0~15>"

4.2 查詢目前 database 資料數量

查詢目前所選擇既 database 既資料數量(key 數量):
# database size DBSIZE

4.3 刪除目前 database 內所有資料

以下指令會刪除目前所選擇既 database 既所有資料:
# flush database FLUSHDB

4.4 刪除所有資料

以下指令會刪除所有 databases 既所有資料:
# flush all FLUSHALL

5 查詢 keys

5.1 KEYS

查詢所有 keys:
KEYS *
我地亦可以使用 glob-style 既 patterns 去查詢 keys,例如用 * 代表任意長度既任意值。
查詢以特定 prefix 開頭既 keys:
KEYS "<key prefix>*"

5.2 SCAN

根據 Redis 官網呢篇關於 KEYS 指令既文檔——KEYS pattern,我地最好唔好喺 Production 環境用 KEYS
Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using SCAN or sets.
查詢以特定 prefix 開頭、特定 data type 既 keys(第一頁,建議返回若干數量):
SCAN "<cursor>" MATCH "<key prefix>*" COUNT "<suggested result count>" TYPE "<string/list/set/zset/hash/stream>"
例子:
MSET a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j 10 k 11 l 12 m 13 n 14 o 15 p 16 q 17 r 18 s 19 t 20 u 21 v 22 w 23 x 24 y 25 z 26 SCAN 0 MATCH "*" COUNT 10 TYPE string SCAN ... SCAN ... (直至返回既 cursor 係 0
結果係由 2 個 elements 組成:
  1. 新既 cursor 數字,畀我地下次再 SCAN 果陣用。
    • 例如佢返回既 cursor 係 22,咁我地下次就將句 command 改成 SCAN 22 MATCH "*" COUNT 10 TYPE string,直至到佢返回 0 既 cursor,咁先至代表已經係完成曬成個 search cycle。
  2. 呢次 SCAN 指令查詢到既分頁結果,以 array 表示,elements 係 keys。
註:
  • 一定要執行 SCAN 指令直至到 Redis 返回既 cursor 數字係 0,否則有可能會 miss 左一啲結果。
  • 每次 SCAN 指令返回既結果數量都可以係意想不到,有可能少過、多過,或者等於我地 COUNT 所建議既數量。
  • KEYS 相似既地方係,返回既結果既次序同佢地新增既次序好可能會唔一樣。
  • 雖然感覺有少少似 SQL SELECTWHERE LIMIT OFFSET 分頁查詢,但實際上有好多唔相似既地方。
    • Redis 會先查詢 keys,之後再應用 MATCH 以及 TYPE 既 filters。
      • 呢個設計有別於 SQL 先應用 WHERE 既條件,然後再應用 LIMIT OFFSET 實現分頁。
      • 咁亦即係話,如果咁岩個分頁既 keys 全部唔中 pattern 或者 data type 既話,呢次 SCAN 既最終分頁查詢結果就會係 empty array,但係下一頁(下一個 SCAN)既結果反而有可能會係 non-empty array。所以一定要執行 SCAN 直至到佢返回 0 既 cursor。
        • It is important to note that the MATCH filter is applied after elements are retrieved from the collection, just before returning data to the client. This means that if the pattern matches very little elements inside the collection, SCAN will likely return no elements in most iterations. An example is shown below:
    • 根據官網,SCAN 有可能會出現重複既結果,所以我地既程式係需要 handle 有重複結果既情況。
      • A given element may be returned multiple times. It is up to the application to handle the case of duplicated elements, for example only using the returned elements in order to perform operations that are safe when re-applied multiple times.
    • 如果有 element(s) 係喺 SCAN loop 進行緊既時候加入,佢地未必會出現喺結果裡面,呢樣野係話唔定。
      • Elements that were not constantly present in the collection during a full iteration, may be returned or not: it is undefined.
    • 如果有 element(s) 係喺 SCAN loop 進行既整個過程裡面都存在,咁佢地就保證一定會出現喺某次既結果裡面。
    • 如果有 element(s) 係喺 SCAN loop 進行既整個過程裡面都唔存在,咁佢地就保證一定唔會出現喺任何結果裡面。
  • COUNT
    • 代表「建議」分頁數量,類似 SQL 既 LIMIT
    • 默認值係 10
    • 呢個數字只係一個「建議」,基於 Redis 對於 SCAN 既處理方式以及 MATCH 既生效次序,Redis 最終唔一定會(好可能唔會)返回 exactly 呢個數量既 keys。
  • SCAN 後面既數字——cursor
    • 感覺上類似 SQL 既 OFFSET,但事實上唔係。呢個數字喺一個完整既 SCAN loop 裡面可以增加亦可以減少。
    • 因為 Redis 唔一定會返回我地 COUNT 所指定既數量,所以下一次再用 SCAN 查詢果陣,SCAN 後面既數字必須要用返目前 SCAN 查詢結果所返回既第 1 個 element 既數字。
    • 一般用法係由 0 開始,直至下一次結果返回既第 1 個 element 係 0,咁先算係查詢曬所有結果(作為一個完整既 SCAN loop)。
      • 但因為冇 server-side state,所以喺一個完整既 SCAN loop 裡面任何時候中斷查詢都冇問題。
  • MATCH
    • KEYS 一樣都係用 glob-style 既 patterns。
    • 佢會喺查詢完分頁既 keys 之後先至生效。
  • TYPE
    • 可以係 stringlistsetzsethash 或者 stream
    • 佢會喺查詢完分頁既 keys 之後先至生效。
參考資料:

5.3 查詢 keys 既存在

查詢一個或多個 key(s) 係咪存在:
EXISTS "<key>" "[<key2>...]"

5.4 查詢 key 既 TTL

查詢一個 key 既 TTL(秒):
TTL <key>

6 Data types

Redis 既 data types 指既係 key-value pair 既 value 所用既儲存格式。
Data type描述
String一般既文字格式,我地亦可以用 JSON 格式黎儲存 nested 既數據。
List基本上就係 Java 既 List 咁,會保留 elements 既新增次序。
Set基本上就係 Java 既 Set 咁,唔容許有重覆既 value。
Hash基本上就係 Java 既 Map 咁。
Sorted Set同 set 相似,但可以根據需要而給予 elements 先後次序。
查詢某一個 key-value pair 既 value data type:
TYPE "<key>"
以下會介紹最主要既幾種 data types:
  • String
  • List
  • Set

6.1 String

查詢 value:
GET "<key>"
新增或覆蓋:
SET "<key>" "<value>"
新增或覆蓋(附失效時間,以秒計):
# set expiration SETEX "<key>" "<timeout in seconds>" "<value>"
刪除:
# get and delete GETDEL "<key>"

6.2 List

List 係冇得好似 Set 咁直接查詢某 value 存在與否。
查詢所有 elements:
# list range LRANGE "<key>" 0 -1
查詢 elements 既數量:
# list length LLEN "<key>"
新增一個或多個 element(s) 喺最前面:
# left push LPUSH "<key>" "<value>" "[<value2>...]"
新增一個或多個 element(s) 喺最後面:
# right push RPUSH "<key>" "<value>" "[<value2>...]"
根據 value 刪除所有匹配既 elements:
# list remove LREM "<key>" 0 "<value>"
刪除最前面既一個或多個 element(s) 並且返回佢或佢地既 value(s):
# left pop LPOP "<key>" "[<count>]"
刪除最後面既一個或多個 element(s) 並且返回佢或佢地既 value(s):
# right pop RPOP "<key>" "[<count>]"

6.3 Set

查詢所有 elements:
# set members SMEMBERS "<key>"
查詢 elements 既數量:
# set cardinality SCARD "<key>"
新增一個或多個 element(s):
# set add SADD "<key>" "<value>" "[<value2>...]"
刪除一個或多個 element(s):
# set remove SREM "<key>" "<value>" "[<value2>...]"
刪除一個或多個任意既 element(s) 並且返回佢或佢地既 value(s):
# set pop SPOP "<key>"
查詢某 value 存在與否:
# set is member SISMEMBER "<key>" "<value>"
查詢一個或多個任意既 element(s) 既 value(s):
# set random member SRANDMEMBER "<key>" "[<count>]"

7 其他指令

7.1 登入

AUTH "<password>"

7.2 查詢客戶端連線資料

CLIENT INFO

7.3 CLI 內建既指令使用手冊

HELP @string HELP @list HELP @set HELP @hash HELP @sorted-set

8 參考資料