[Redis] Getting Started
TL;DR
# 進入 Redis,預設會是 localhost:6379
$ redis-cli # local redis
# 基本操作
> SET framework react
> GET framework # react
> KEYS * # 取得 redis 中所有的 key
> DEL framework
# 其他操作
> TYPE <key> # 檢視型別
# EXPIRE key seconds # 設定 key 過期的時間(自動刪除)
# TTL key # 檢視 key 剩多久會過期
> SET notification "some people fall down"
> EXPIRE notification 30 # 30 秒後會過期
> TTL notification # 檢視剩餘時間(秒);-1 表示該 key 沒有設定過期時間;-2 表示該 key 曾經存在但已過期或被刪除
# 根據 pattern 刪除多筆資料
> redis-cli --scan --pattern "cache:user:*" | xargs redis-cli unlink
安裝 Redis
brew install redis
brew services start redis
另外 Redis 也有還不錯用的 GUI 工具,雖然長得有點像強國國旗:
AnotherRedisDesktopManager @ GitHub
連接到 Redis
- Connect to Redis:連結到 redis 的各種方式(包括 localhost、remote、Redis Cloud、Docker container 等等)
# 進入 Redis,預設會是 localhost:6379
$ redis-cli # local redis
$ redis-cli -h 192.168.0.10 -p 7000 # remote redis
測試連線:
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> get foo
"bar"
Key
- Redis 當中的 Key 就是 binary safe 的 string,可以是
"foo"
,42
,3.1415
,0xff
- 由於 Key 本身是 binary 的序列,因此大小寫是有區別的(case sensitive),下面這三組分別都是不同的 Key
registeredusers:1000:followers
registeredUsers:1000:followers
RegisteredUsers:1000:followers
- 太長的 key 是不建議的,必須在「容易閱讀的 Key」和「使用的記憶體容量」間做取捨
- 命名慣例上會用冒號(
:
)做為區隔,例如user:1000:followers
- user: object name
- 1000: user ID
- followers: composed object
Logical Databases
- Logical Database 中並沒有 name space 的概念,也就是所有的 key 都是在水平的同一層內,而沒有以 documents 或 collections 的概念
- Logical Database 會用 zero-based 的 index 來辨別(也就是以 0 開始)。
- 同一 database 中的 key 不能重複;但不同 database 中的 key 可以重複
搜尋 Keys:KEYS and SCAN
如果要取得一系列的 Key 可以使用 KEYS
或 SCAN
這兩個指令:
KEYS
:可以在本地開發時除錯(Debug)用,但千萬不要用在 Production 上。直到全部完成前會阻塞。SCAN
:用在 production 中,雖然它也阻塞,但一次只會迭代(iterate)一定數量的 keys。
使用 KEYS
# 使用 * 表示萬用字元(wild card)
> keys customer:10*
使用 SCAN
COUNT
越大則會一次會搜尋越多的量,但因為是阻塞操作的緣故,對效能影響越大- 當沒有更多的 KEY 要 iterate 時,
cursor
會回傳 0
# SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
> SCAN 0 MATCH customer:10*
1) "15" # cursor 是 15
2) 1) "customer:1000"
2) "customer:1001"
> SCAN 15 MATCH customer:10*
1) "0"
2) (empty array)
移除 Keys:DEL and UNLINK
DEL
會移除掉 KEY 及其相關的記憶體,處理的方式是阻塞的UNLINK
會把 KEY 給移除,而和該 KEY 有關記憶體的清理則是以非同步的方式處理(non-blocking)
> UNLINK customer:1000
(integer) 1
確認 Key 是否存在:EXISTS
> EXISTS customer:1001
(integer) 1
Data Types
Data types @ redis
- Binary-safe Strings:可以儲存任何的字串,不論是 PNG 或序列化過的物件
- Lists:本質上是 linked-list,根據被建立的順序可以進行排序。由於是 linked-list 的緣故,它在新增和刪除元素的速度是快的,但搜尋速度是相對慢的。
- Sets:一系列未排序(unsorted)且唯一(unique)的字串
- Sorted Sets:一系列唯一的字串,但每一個字串都和 float number 連結在一起(稱作
score
),因此可以透過 score 進行排序 - Hashes:類似 map,其 key 和 value 都是字串
- Bit arrays:又稱作 bitmaps,它讓開發者可以把字串作為 array of bits 處理。
- HyperLogLogs:用來測量 set 中 element 的數量
String
keywords: SET
, GET
, SETNX
, SETEX
, INCR
, DECR
, INCRBY
, DECRBY
- Binary-safe String 的意思是可以儲存任何形式的字串,例如 JPEG 檔或序列化過的物件
- String 最大可以到 512MB
# SET key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX]
> SET phone Note10 EX 10 # 10 秒過期
> SET price 23900
# SETNX key value # SET if Not Exist,如果該 key 不存在才儲存
> SETNX frameworks "react vue angular" # 回傳 1 表示成功,0 表示失敗(該 key 已經存在)
# SETEX key seconds value # 設定過期時間
# 增加或減少數值
> INCR price # 23901,一次增加 1
> DECR price # 23900,一次減少 1
> INCRBY price 1000 # 24900,一次增加 1000
> DECRBY price 1000 # 23900,一次減少 1000
List
keywords: RPUSH
, LPUSH
, LRANGE
, LLEN
, LPOP
, RPOP
- 有順序性
- 新增刪除相對快:適合用在只要取出頭尾元素的情況(例如 Queue)
- 搜尋速度相對慢
- 適用時機
- Message Queue:因為只需要取出頭、尾的元素而不需要搜尋
由於 Lists 本質上是 linked-list 的緣故,它在新增和刪除元素的速度是快的,但搜尋速度是相對慢的。可以使用 RPUSH
和 LPUSH
來新增元素,如果該 key 尚不存在的話,會回傳新的 List,如果該 key 已經存在,或它不是 List 的話,則會回傳錯誤。
# 在 List 中新增元素
# RPUSH <key> <element> [element ...] / LPUSH <key> <element> [element ...]
> RPUSH frameworks react vue angular # 3
> LPUSH frameworks svelte # 4
# 檢視 List 中的元素
# LRANGE <key> <start> <stop>
> LRANGE frameworks 0 -1 # 列出所有元素,-1 表示 list 中的最後一個元素
# 檢視 List 數目
# LLEN <key>
> LLEN frameworks
# 移除 list 中的元素
# RPOP <key> / LPOP <key>
> RPOP frameworks # 移除 list 最後一個元素
> LPOP frameworks
Set
keywords: SADD
, SREM
, SMEMBERS
, SISMEMBER
, SUNION
- 沒有順序性
- 元素值會是唯一:重複的話不會新增,因此不需要在添加元素前先檢查該元素是否存在
- 使用時機
- 紀錄每一個造訪的 IP(因為重複的話不會再次被記錄)
- 商品的標籤(Tag)
Sets 和 List 很類似,但它並「沒有順序性」而且元素需要是「唯一」的使用 SADD
來建立 Set:
# SADD <key> <member> [member ...] # 新增元素到 Set 中
> SADD languages english # 1,新增的元素數目
> SADD languages frensh chinese # 2,新增的元素數目
> SADD languages english # 0,如果元素已經在該 Sets 中,會回傳 0
# SREM <key> <member> [member...] # 從 Set 中移除元素
> SREM languages english # 1,移除的元素數目
# SMEMBERS <key> # 檢視 Set 中所有元素
> SMEMBERS languages # 回傳的元素沒有順序性
# SISMEMBER <key> <member> # 檢視元素是否存在該 Set 中
> SISMEMBER languages chinese # 1,存在的話回傳 1,不存在則回傳 0
# SUNION <key> [key...] # 合併多個 Sets
> SUNION languages programming-languages
- 使用
SADD
時,如果新增的元素已經存在 SET 中,則不會新增 - 使用
SUNION
時,如果欲合併的 Set 不存在,則會視為合併了一個空的 Set
Hash
keywords: HSET
, HGET
, HGETALL
, HMSET
, HMGET
在 Redis 中,Hash 可以用來保存類似物件,也就是 key 配到的是「field-value pairs」
# HSET <key> <field> <value> [field value...] # 新增 field-value pairs 到 Hash 中
> HSET phone name "iphone" # 1,新增的數目
> HSET phone price 22500 # 1,新增的數目
> HSET phone storage 128 ram 4 # 2,新增的數目
> HSET phone name "iphone mini" # 0,表示該 field 已經存在 hash 中,將會「更新」其 value
# HGET <key> <field> # 取得 field 的 value
> HGET phone name # "iphone mini"
# HGETALL <key> # 取得所該 hash 對所有值
> HGETALL phone
# HMSET <key> <field> <value> [field value...] # 和 HSET 相同
# HMGET <key> <field> [field...] # 一次取出多個 field 的值
> HMGET phone name price
Sorted Set
keywords: ZADD
, ZRANGE
, ZCARD
, ZSCORE
, ZCOUNT
, ZINCRBY
- 有順序性,透過與
score
產生連結來達到排序的作用,score
本身會是 float - 元素值仍然是唯一,但
score
可以不是唯一 - 不論是 Add, Remove 或 Update 的速度都很快,同時可以快速搜尋位於中間的項目
- 可以視為 Set 和 Hash 的混合
- 使用上指令和 Set 相似,只要把最開頭的
S
改成Z
- 使用時機
- 遊戲的計分板
# ZADD <key> [NX|XX] [CH] [INCR] <score> <member> [score member ...],新增 sorted Set
> ZADD students 1 aaron # 1
> ZADD students 2 allison # 1
> ZADD students 3 bruce 4 derek # 2
# XX:只更新已存在的 member 的 score,絕不新增 member
# NX:不更新以存在的 member 的 score,總是新增 member
> ZADD students XX 10 aaron # 如果 aaron 存在,則將 score 更新為 10
> ZADD students NX
> ZADD students NX 777 jen # 如果 jen 不存在,則新增且將 score 設為 777
# ZRANGE <key> <start> <stop> [WITHSCORES],檢視 sorted set
> ZRANGE students 0 -1 # 檢視 sorted set 中所有元素
# ZCARD <key>,檢視該 set 中的元素數目
> ZCARD students
# ZCOUNT <key> <min> <max> # 檢視分數介於 min ~ max 間的元素拭目
> ZCOUNT students 0 10
# ZSCORE <key> <member> # 檢視某 member 的 score
> ZSCORE students aaron
# ZINCRBY <key> <increment> <member> # 幫 member 的 score 分數增加
> ZINCRBY students 10 aaron # 幫 aaron 的 score 加 10
Bitmaps and HyperLogLogs
參考資料
- Introduction to Redis Data Structures @ redislab
- Data types @ redis
- Introduction to Redis: Installation, CLI Commands, and Data Types @ OAuth0
- Go 繁不及備載:Day29 Go-安裝 Redis 鍵值資料庫 @ iT 邦幫忙鐵人賽
- Go 繁不及備載:Day30 Go-Redis 鍵值資料庫實作小遊戲 @ iT 邦幫忙鐵人賽