Redis 實戰 —— 04. Redis 資料結構常用命令簡介
阿新 • • 發佈:2021-01-23
#### 字串 `P39`
Redis 的字串是一個有位元組組成的序列,可以儲存以下 3 種類型的值:位元組串(byte string)、整數、浮點數。
在需要的時候, Redis 會將整數轉換成浮點數。整數的取值範圍和系統的長整型(long)的相同,浮點數取值範圍和精度與 IEEE 754 標準下的雙精度浮點數(double)的相同。
##### Redis 中的自增命令和自減命令 `P39`
| 命令 | 格式 | 描述 |
| ----------- | ------------------------- | ---------------------------------------- |
| INCR | INCR key | 將鍵儲存的數字值加上 1 |
| DECR | DECR key | 將鍵儲存的數字值減去 1 |
| INCRBY | INCRBY key increment | 將鍵儲存的數字值加上整數增量 increment |
| DECRBY | DECRBY key decrement | 將鍵儲存的數字值減去整數減量 decrement |
| INCRBYFLOAT | INCRBYFLOAT key increment | 將鍵儲存的數字值加上浮點數增量 increment |
相關演示程式碼如下(`main` 及 `handleResult` 定義見:[01. Redis 資料結構簡介](https://mp.weixin.qq.com/s/vUsOfARXsM8H1ts6mC5tmA)):
```go
// 執行字串型別數字相關操作
func executeNumberOperation(conn redis.Conn) {
// 刪除原有值
handleResult(redis.Int(conn.Do("DEL", "number")))
// 獲取值,輸出 -> ERROR: redigo: nil returned
handleResult(redis.Int(conn.Do("GET", "number")))
// 自增 1,返回自增後的值 -> 1
handleResult(redis.Int(conn.Do("INCR", "number")))
// 自增 2,返回自增後的值 -> 3
handleResult(redis.Int(conn.Do("INCRBY", "number", "2")))
// 自減 1,返回自減後的值 -> 2
handleResult(redis.Int(conn.Do("DECR", "number")))
// 自減 2,返回自減後的值 -> 0
handleResult(redis.Int(conn.Do("DECRBY", "number", "2")))
// 自增 1.5,返回自增後的值 -> 1.5
handleResult(redis.Float64(conn.Do("INCRBYFLOAT", "number", "1.5")))
// 自增 -1.3,返回自增後的值 -> 0.2
handleResult(redis.Float64(conn.Do("INCRBYFLOAT", "number", "-1.3")))
}
```
##### 供 Redis 處理子串和二進位制位的命令 `P40`
| 命令 | 格式 | 描述 |
| -------- | ------------------------------------- | ------------------------------------------------------------ |
| APPEND | APPEND key value | 將 value 追加到 key 當前值的末尾 |
| GETRANGE | GETRANGE key start end | 返回 [start, end] 範圍內子串 |
| SETRANGE | SETRANGE key offset value | 將子串 [offset, offset + len(value)) 設定為 value |
| GETBIT | GETBIT key offset | 將字串看作是二進位制位串,獲取 offset 上的位 |
| SETBIT | SETBIT key offset value | 將字串看作是二進位制位串,設定 offset 上的位為 value |
| BITCOUNT | BITCOUNT key [start end] | 統計 [start, end] 範圍內子串在二進位制下有多少個 1 |
| BITOP | BITOP operation destkey key [key ...] | operation 可選位運算 AND , OR , XOR , NOT ,將一個或多個二進位制位串執行的操作結果存到 destkey 中 |
相關演示程式碼如下:
```go
// 執行字串型別字串相關操作
func executeStringOperation(conn redis.Conn) {
// 刪除原有值
handleResult(redis.Int(conn.Do("DEL", "string")))
// 追加串,返回當前字串長度 -> 6,值變為 -> append
handleResult(redis.Int(conn.Do("APPEND", "string", "append")))
// 獲取子串,返回 -> en
handleResult(redis.String(conn.Do("GETRANGE", "string", 3, 4)))
// 設定子串,返回當前字串長度 -> 6,值變為 -> appled
handleResult(redis.Int(conn.Do("SETRANGE", "string", 3, "le")))
// 設定子串,返回當前字串長度 -> 11,值變為 -> application
handleResult(redis.Int(conn.Do("SETRANGE", "string", 3, "lication")))
// 獲取二進位制位,返回 -> 1
// (獲取第 7/8 個字元 a 在二進位制下第 7%8 位上的二進位制位,即 0110 0001 的第 7 位 1)
handleResult(redis.Int(conn.Do("GETBIT", "string", 7)))
// 設定二進位制位,返回原來的二進位制位 -> 0,值變為 -> cpplication
// (設定第 6/8 個字元 a 在二進位制下第 6%8 位上的二進位制位為1,即 0110 0001 變為 0110 0011)
handleResult(redis.Int(conn.Do("SETBIT", "string", 6, 1)))
// 統計二進位制位,返回 -> 7
// (統計 [0, 1] 範圍內子串 cp 在二進位制下 0110 0011 0111 0000 二進位制位為 1 的數量)
handleResult(redis.Int(conn.Do("BITCOUNT", "string", 0, 1)))
handleResult(redis.String(conn.Do("SET", "aKey", "aa")))
handleResult(redis.String(conn.Do("SET", "bKey", "b")))
// 對 aa(0110 0001 0110 0001) 和 b(0110 0010 0000 0000) 進行 按位或,結果儲存到 cKey 中
// 返回字串長度 -> 2,值為 ca(0110 0011 0110 0001),
handleResult(redis.Int(conn.Do("BITOP", "OR", "cKey", "aKey", "bKey")))
}
```
Redis 可以通過使用子串操作和二進位制位操作,配合 `WATCH` 、`MULTI` 和 `EXEC` 命令(後面會初步介紹,以後將深入講解),構建任何想要的資料結構。
#### 列表 `P42`
##### 一些常用的列表命令 `P42`
| 命令 | 格式 | 描述 |
| ------ | --------------------------- | ---------------------------------------------- |
| RPUSH | RPUSH key value [value ...] | 依次將一個或多個 value 從列表右端插入 |
| LPUSH | LPUSH key value [value ...] | 依次將一個或多個 value 從列表左端插入 |
| RPOP | RPOP key | 移除並返回列表最右端的元素 |
| LPOP | LPOP key | 移除並返回列表最左端的元素 |
| LINDEX | LINDEX key offset | 返回列表左端開始偏移量為 offset 的元素 |
| LRANGE | LRANGE key start end | 返回列表左端開始 [start, end] 範圍內的所有元素 |
| LTRIM | LTRIM key start end | 移除列表左端開始 [start, end] 範圍外的所有元素 |
相關演示程式碼如下:
```go
// 執行列表型別相關操作
func executeListOperation(conn redis.Conn) {
// 刪除原有值
handleResult(redis.Int(conn.Do("DEL", "list")))
// 右端插入一次插入 a, b, c,返回當前列表長度 -> 3,列表變為 -> a b c
handleResult(redis.Int(conn.Do("RPUSH", "list", "a", "b", "c")))
// 左端插入一次插入 d, e, f,返回當前列表長度 -> 6,列表變為 -> f e d a b c
handleResult(redis.Int(conn.Do("LPUSH", "list", "d", "e", "f")))
// 彈出並返回列表最右端的值,返回 -> c,列表變為 -> f e d a b
handleResult(redis.String(conn.Do("RPOP", "list")))
// 彈出並返回列表最左端的值,返回 -> f,列表變為 -> e d a b
handleResult(redis.String(conn.Do("LPOP", "list")))
// 返回左端開始下標偏移量為 offset 的值,返回 -> d
handleResult(redis.String(conn.Do("LINDEX", "list", 1)))
// 移除列表左端開始 [1, 2] 範圍外的所有元素,列表變為 -> d a
handleResult(redis.String(conn.Do("LTRIM", "list", 1, 2)))
}
```
利用 `LTRIM` 命令可以原子地彈出多個元素。 `P43`
##### 阻塞式的列表彈出命令以及在列表之間移動元素的命令 `P43`
| 命令 | 格式 | 描述 |
| ---------- | ------------------------------------- | ------------------------------------------------------------ |
| BLPOP | BLPOP key [key ...] timeout | 從第一個非空列表中彈出最左端的元素,或者在 timeout 秒內阻塞並等待可彈出的元素出現,返回被彈出的列表名及元素, timeout 為 0 表示無限等待 |
| BRPOP | BRPOP key [key ...] timeout | 從第一個非空列表中彈出最右端的元素,或者在 timeout 秒內阻塞並等待可彈出的元素出現,返回被彈出的列表名及元素, timeout 為 0 表示無限等待 |
| RPOPLPUSH | RPOPLPUSH source destination | 從 source 列表中彈出最右端的元素,然後將這個元素退出 destination 列表的最左端,並返回這個元素 |
| BRPOPLPUSH | BRPOPLPUSH source destination timeout | 從 source 列表中彈出最右端的元素,然後將這個元素退出 destination 列表的最左端,並返回這個元素;如果 source 列表為空,則在 timeout 秒內阻塞並等待可彈出元素出現 |
相關演示程式碼如下:
```go
// 執行列表型別阻塞相關操作
func executeListBlockOperation(conn redis.Conn) {
// 刪除原有值
handleResult(redis.Int(conn.Do("DEL", "source", "destination")))
// 從第一個非空列表中彈出並返回列表最左端的值,最多等待 1秒,輸出 -> ERROR: redigo: nil returned
handleResult(redis.Strings(conn.Do("BLPOP", "source", "destination", 1)))
// 初始化
handleResult(redis.Int(conn.Do("RPUSH", "source", "a", "b", "c")))
handleResult(redis.Int(conn.Do("RPUSH", "destination", "d", "e", "f")))
// 從第一個非空列表中彈出並返回列表最左端的值,無限等待,返回 -> a,source 變為 -> b c,destination 變為 -> d e f
handleResult(redis.Strings(conn.Do("BLPOP", "source", "destination", 0)))
// 從第一個非空列表中彈出並返回列表最右端的值,無限等待,返回 -> f,source 變為 -> b c,destination 變為 -> d e
handleResult(redis.Strings(conn.Do("BRPOP", "destination", "source", 0)))
// 從 source 彈出最右端元素,然後推入到 destination 最左端,並返回這個元素
// 返回 -> c,source 變為 -> b,destination 變為 -> c d e
handleResult(redis.String(conn.Do("RPOPLPUSH", "source", "destination")))
// 從 source 彈出最右端元素,然後推入到 destination 最左端,並返回這個元素,無限等待
// 返回 -> b,source 變