Redis 常用命令

Redis

是什麼

  • 基於內存的支持持久化
  • k:v NOSQL 數據庫

用途

  • 緩存、數據庫、消息中間件

RedisDesktopManger

功能

  • 持久化功能
  • 發佈訂閱功能
  • 事務功能
  • 過期鍵功能
  • 複製
  • 集羣

Redis

  • Redis 是一個開源的,基於內存的結構化數據存儲媒介,可以作爲數據庫、緩存服務或消息服務使用。
  • Redis支持多種數據結構,包括字符串、哈希表、鏈表、集合、有序集合、位圖、Hyperloglogs 等。
  • Redis具備LRU淘汰、事務實現、以及不同級別的硬盤持久化等能力,並且支持副本集和通過
  • RedisSentinel實現的高可用方案,同時還支持通過RedisCluster實現的數據自動分片能力。

Redis 的主要功能都基於單線程模型實現,也就是說 Redis 使用一個線程來服務所有的客戶端請求,同時 Redis 採用了非阻塞式 IO,並精細地優化各種命令的算法時間複雜度,這些信息意味着:

Redis 是線程安全的(因爲只有一個線程),其所有操作都是原子的,不會因併發產生數據異常

Redis 的速度非常快(因爲使用非阻塞式 IO,且大部分命令的算法時間複雜度都是 O(1))

使用高耗時的 Redis 命令是很危險的,會佔用唯一的一個線程的大量處理時間,導致所有的請求都被拖慢。(例如時間複雜度爲 O(N) 的 KEYS 命令,嚴格禁止在生產環境中使用)

本文只對 Redis 命令進行扼要的介紹,且只列出了較常用的命令。如果想要了解完整的 Redis 命令集,或瞭解某個命令的詳細使用方法,請參考官方文檔:https://redis.io/commands

常用命令一:Key

Redis 採用 Key-Value 型的基本數據結構,任何二進制序列都可以作爲 Redis 的 Key 使用(例如普通的字符串或一張 JPEG 圖片)

關於 Key 的一些注意事項:

不要使用過長的 Key。例如使用一個 1024 字節的 key 就不是一個好主意,不僅會消耗更多的內存,還會導致查找的效率降低

Key 短到缺失了可讀性也是不好的,例如”u1000flw” 比起”user:1000:followers” 來說,節省了寥寥的存儲空間,卻引發了可讀性和可維護性上的麻煩

最好使用統一的規範來設計 Key,比如”object-type:id:attr”,以這一規範設計出的 Key 可能是”user:1000” 或”comment:1234:reply-to”

Redis 允許的最大 Key 長度是 512MB(對 Value 的長度限制也是 512MB)

常用命令二:String

String 是 Redis 的基礎數據類型,Redis 沒有 Int、Float、Boolean 等數據類型的概念,所有的基本類型在 Redis 中都以 String 體現。

與 String 相關的常用命令:

SET:爲一個 key 設置 value,可以配合 EX/PX 參數指定 key 的有效期,通過 NX/XX 參數針對 key 是否存在的情況進行區別操作,時間複雜度 O(1)

GET:獲取某個 key 對應的 value,時間複雜度 O(1)

GETSET:爲一個 key 設置 value,並返回該 key 的原 value,時間複雜度 O(1)

MSET:爲多個 key 設置 value,時間複雜度 O(N)

MSETNX:同 MSET,如果指定的 key 中有任意一個已存在,則不進行任何操作,時間複雜度 O(N)

MGET:獲取多個 key 對應的 value,時間複雜度 O(N)

上文提到過,Redis 的基本數據類型只有 String,但 Redis 可以把 String 作爲整型或浮點型數字來使用,主要體現在 INCR、DECR 類的命令上:

INCR:將 key 對應的 value 值自增 1,並返回自增後的值。只對可以轉換爲整型的 String 數據起作用。時間複雜度 O(1)

INCRBY:將 key 對應的 value 值自增指定的整型數值,並返回自增後的值。只對可以轉換爲整型的 String 數據起作用。時間複雜度 O(1)

DECR/DECRBY:同 INCR/INCRBY,自增改爲自減。

INCR/DECR 系列命令要求操作的 value 類型爲 String,並可以轉換爲 64 位帶符號的整型數字,否則會返回錯誤。

也就是說,進行 INCR/DECR 系列命令的 value,必須在 [-2^63 ~ 2^63 - 1] 範圍內。

前文提到過,Redis 採用單線程模型,天然是線程安全的,這使得 INCR/DECR 命令可以非常便利的實現高併發場景下的精確控制。

例 1:庫存控制
在高併發場景下實現庫存餘量的精準校驗,確保不出現超賣的情況。

設置庫存總量:

SET inv:remain “100”

庫存扣減 + 餘量校驗:

DECR inv:remain

當 DECR 命令返回值大於等於 0 時,說明庫存餘量校驗通過,如果返回小於 0 的值,則說明庫存已耗盡。

假設同時有 300 個併發請求進行庫存扣減,Redis 能夠確保這 300 個請求分別得到 99 到 - 200 的返回值,每個請求得到的返回值都是唯一的,絕對不會找出現兩個請求得到一樣的返回值的情況。

例 2:自增序列生成
實現類似於 RDBMS 的 Sequence 功能,生成一系列唯一的序列號

設置序列起始值:

SET sequence “10000”

獲取一個序列值:

INCR sequence

直接將返回值作爲序列使用即可。

獲取一批(如 100 個)序列值:

INCRBY sequence 100

假設返回值爲 N,那麼 [N - 99 ~ N] 的數值都是可用的序列值。

當多個客戶端同時向 Redis 申請自增序列時,Redis 能夠確保每個客戶端得到的序列值或序列範圍都是全局唯一的,絕對不會出現不同客戶端得到了重複的序列值的情況。

常用命令三:List

Redis 的 List 是鏈表型的數據結構,可以使用 LPUSH/RPUSH/LPOP/RPOP 等命令在 List 的兩端執行插入元素和彈出元素的操作。雖然 List 也支持在特定 index 上插入和讀取元素的功能,但其時間複雜度較高(O(N)),應小心使用。

與 List 相關的常用命令:

LPUSH:向指定 List 的左側(即頭部)插入 1 個或多個元素,返回插入後的 List 長度。時間複雜度 O(N),N 爲插入元素的數量

RPUSH:同 LPUSH,向指定 List 的右側(即尾部)插入 1 或多個元素

LPOP:從指定 List 的左側(即頭部)移除一個元素並返回,時間複雜度 O(1)

RPOP:同 LPOP,從指定 List 的右側(即尾部)移除 1 個元素並返回

LPUSHX/RPUSHX:與 LPUSH/RPUSH 類似,區別在於,LPUSHX/RPUSHX 操作的 key 如果不存在,則不會進行任何操作

LLEN:返回指定 List 的長度,時間複雜度 O(1)

LRANGE:返回指定 List 中指定範圍的元素(雙端包含,即 LRANGE key 0 10 會返回 11 個元素),時間複雜度 O(N)。應儘可能控制一次獲取的元素數量,一次獲取過大範圍的 List 元素會導致延遲,同時對長度不可預知的 List,避免使用 LRANGE key 0 -1 這樣的完整遍歷操作。

應謹慎使用的 List 相關命令:

LINDEX:返回指定 List 指定 index 上的元素,如果 index 越界,返回 nil。index 數值是迴環的,即 - 1 代表 List 最後一個位置,-2 代表 List 倒數第二個位置。時間複雜度 O(N)

LSET:將指定 List 指定 index 上的元素設置爲 value,如果 index 越界則返回錯誤,時間複雜度 O(N),如果操作的是頭 / 尾部的元素,則時間複雜度爲 O(1)

LINSERT:向指定 List 中指定元素之前 / 之後插入一個新元素,並返回操作後的 List 長度。如果指定的元素不存在,返回 - 1。如果指定 key 不存在,不會進行任何操作,時間複雜度 O(N)

由於 Redis 的 List 是鏈表結構的,上述的三個命令的算法效率較低,需要對 List 進行遍歷,命令的耗時無法預估,在 List 長度大的情況下耗時會明顯增加,應謹慎使用。

換句話說,Redis 的 List 實際是設計來用於實現隊列,而不是用於實現類似 ArrayList 這樣的列表的。如果你不是想要實現一個雙端出入的隊列,那麼請儘量不要使用 Redis 的 List 數據結構。

爲了更好支持隊列的特性,Redis 還提供了一系列阻塞式的操作命令,如 BLPOP/BRPOP 等,能夠實現類似於 BlockingQueue 的能力,即在 List 爲空時,阻塞該連接,直到 List 中有對象可以出隊時再返回。針對阻塞類的命令,此處不做詳細探討,請參考官方文檔(https://redis.io/topics/data-types-intro) 中”Blocking operations on lists” 一節。

常用命令四:Hash

Hash 即哈希表,Redis 的 Hash 和傳統的哈希表一樣,是一種 field-value 型的數據結構,可以理解成將 HashMap 搬入 Redis。

Hash 非常適合用於表現對象類型的數據,用 Hash 中的 field 對應對象的 field 即可。

Hash 的優點包括:

可以實現二元查找,如” 查找 ID 爲 1000 的用戶的年齡”

比起將整個對象序列化後作爲 String 存儲的方法,Hash 能夠有效地減少網絡傳輸的消耗

當使用 Hash 維護一個集合時,提供了比 List 效率高得多的隨機訪問命令

與 Hash 相關的常用命令:

HSET:將 key 對應的 Hash 中的 field 設置爲 value。如果該 Hash 不存在,會自動創建一個。時間複雜度 O(1)

HGET:返回指定 Hash 中 field 字段的值,時間複雜度 O(1)

HMSET/HMGET:同 HSET 和 HGET,可以批量操作同一個 key 下的多個 field,時間複雜度:O(N),N 爲一次操作的 field 數量

HSETNX:同 HSET,但如 field 已經存在,HSETNX 不會進行任何操作,時間複雜度 O(1)

HEXISTS:判斷指定 Hash 中 field 是否存在,存在返回 1,不存在返回 0,時間複雜度 O(1)

HDEL:刪除指定 Hash 中的 field(1 個或多個),時間複雜度:O(N),N 爲操作的 field 數量

HINCRBY:同 INCRBY 命令,對指定 Hash 中的一個 field 進行 INCRBY,時間複雜度 O(1)

應謹慎使用的 Hash 相關命令:

HGETALL:返回指定 Hash 中所有的 field-value 對。返回結果爲數組,數組中 field 和 value 交替出現。時間複雜度 O(N)

HKEYS/HVALS:返回指定 Hash 中所有的 field/value,時間複雜度 O(N)

上述三個命令都會對 Hash 進行完整遍歷,Hash 中的 field 數量與命令的耗時線性相關,對於尺寸不可預知的 Hash,應嚴格避免使用上面三個命令,而改爲使用 HSCAN 命令進行遊標式的遍歷,具體請見 https://redis.io/commands/scan

常用命令五:Set

Redis Set 是無序的,不可重複的 String 集合。

與 Set 相關的常用命令:

SADD:向指定 Set 中添加 1 個或多個 member,如果指定 Set 不存在,會自動創建一個。時間複雜度 O(N),N 爲添加的 member 個數

SREM:從指定 Set 中移除 1 個或多個 member,時間複雜度 O(N),N 爲移除的 member 個數

SRANDMEMBER:從指定 Set 中隨機返回 1 個或多個 member,時間複雜度 O(N),N 爲返回的 member 個數

SPOP:從指定 Set 中隨機移除並返回 count 個 member,時間複雜度 O(N),N 爲移除的 member 個數

SCARD:返回指定 Set 中的 member 個數,時間複雜度 O(1)

SISMEMBER:判斷指定的 value 是否存在於指定 Set 中,時間複雜度 O(1)

SMOVE:將指定 member 從一個 Set 移至另一個 Set

慎用的 Set 相關命令:

SMEMBERS:返回指定 Hash 中所有的 member,時間複雜度 O(N)

SUNION/SUNIONSTORE:計算多個 Set 的並集並返回 / 存儲至另一個 Set 中,時間複雜度 O(N),N 爲參與計算的所有集合的總 member 數

SINTER/SINTERSTORE:計算多個 Set 的交集並返回 / 存儲至另一個 Set 中,時間複雜度 O(N),N 爲參與計算的所有集合的總 member 數

SDIFF/SDIFFSTORE:計算 1 個 Set 與 1 或多個 Set 的差集並返回 / 存儲至另一個 Set 中,時間複雜度 O(N),N 爲參與計算的所有集合的總 member 數。

上述幾個命令涉及的計算量大,應謹慎使用,特別是在參與計算的 Set 尺寸不可知的情況下,應嚴格避免使用。可以考慮通過 SSCAN 命令遍歷獲取相關 Set 的全部 member(具體請見 https://redis.io/commands/scan ),如果需要做並集 / 交集 / 差集計算,可以在客戶端進行,或在不服務實時查詢請求的 Slave 上進行。

常用命令六:Sorted Set

Redis Sorted Set 是有序的、不可重複的 String 集合。Sorted Set 中的每個元素都需要指派一個分數 (score),Sorted Set 會根據 score 對元素進行升序排序。如果多個 member 擁有相同的 score,則以字典序進行升序排序。
Sorted Set 非常適合用於實現排名。

Sorted Set 的主要命令:

ZADD:向指定 Sorted Set 中添加 1 個或多個 member,時間複雜度 O(Mlog(N)),M 爲添加的 member 數量,N 爲 Sorted Set 中的 member 數量

ZREM:從指定 Sorted Set 中刪除 1 個或多個 member,時間複雜度 O(Mlog(N)),M 爲刪除的 member 數量,N 爲 Sorted Set 中的 member 數量

ZCOUNT:返回指定 Sorted Set 中指定 score 範圍內的 member 數量,時間複雜度:O(log(N))

ZCARD:返回指定 Sorted Set 中的 member 數量,時間複雜度 O(1)

ZSCORE:返回指定 Sorted Set 中指定 member 的 score,時間複雜度 O(1)

ZRANK/ZREVRANK:返回指定 member 在 Sorted Set 中的排名,ZRANK 返回按升序排序的排名,ZREVRANK 則返回按降序排序的排名。時間複雜度 O(log(N))

ZINCRBY:同 INCRBY,對指定 Sorted Set 中的指定 member 的 score 進行自增,時間複雜度 O(log(N))

慎用的 Sorted Set 相關命令:

ZRANGE/ZREVRANGE:返回指定 Sorted Set 中指定排名範圍內的所有 member,ZRANGE 爲按 score 升序排序,ZREVRANGE 爲按 score 降序排序,時間複雜度 O(log(N)+M),M 爲本次返回的 member 數

ZRANGEBYSCORE/ZREVRANGEBYSCORE:返回指定 Sorted Set 中指定 score 範圍內的所有 member,返回結果以升序 / 降序排序,min 和 max 可以指定爲 - inf 和 + inf,代表返回所有的 member。時間複雜度 O(log(N)+M)

ZREMRANGEBYRANK/ZREMRANGEBYSCORE:移除 Sorted Set 中指定排名範圍 / 指定 score 範圍內的所有 member。時間複雜度 O(log(N)+M)

上述幾個命令,應儘量避免傳遞 [0 -1] 或 [-inf +inf] 這樣的參數,來對 Sorted Set 做一次性的完整遍歷,特別是在 Sorted Set 的尺寸不可預知的情況下。可以通過 ZSCAN 命令來進行遊標式的遍歷(具體請見 https://redis.io/commands/scan ),或通過 LIMIT 參數來限制返回 member 的數量(適用於 ZRANGEBYSCORE 和 ZREVRANGEBYSCORE 命令),以實現遊標式的遍歷。

常用命令七:Bitmap 和 HyperLogLog

Redis 的這兩種數據結構相較之前的並不常用,在本文中只做簡要介紹,如想要詳細瞭解這兩種數據結構與其相關的命令,請參考官方文檔 https://redis.io/topics/data-types-intro 中的相關章節

Bitmap 在 Redis 中不是一種實際的數據類型,而是一種將 String 作爲 Bitmap 使用的方法。可以理解爲將 String 轉換爲 bit 數組。使用 Bitmap 來存儲 true/false 類型的簡單數據極爲節省空間。

HyperLogLogs 是一種主要用於數量統計的數據結構,它和 Set 類似,維護一個不可重複的 String 集合,但是 HyperLogLogs 並不維護具體的 member 內容,只維護 member 的個數。也就是說,HyperLogLogs 只能用於計算一個集合中不重複的元素數量,所以它比 Set 要節省很多內存空間。

 其他常用命令

EXISTS:判斷指定的 key 是否存在,返回 1 代表存在,0 代表不存在,時間複雜度 O(1)

DEL:刪除指定的 key 及其對應的 value,時間複雜度 O(N),N 爲刪除的 key 數量

EXPIRE/PEXPIRE:爲一個 key 設置有效期,單位爲秒或毫秒,時間複雜度 O(1)

TTL/PTTL:返回一個 key 剩餘的有效時間,單位爲秒或毫秒,時間複雜度 O(1)

RENAME/RENAMENX:將 key 重命名爲 newkey。使用 RENAME 時,如果 newkey 已經存在,其值會被覆蓋;使用 RENAMENX 時,如果 newkey 已經存在,則不會進行任何操作,時間複雜度 O(1)

TYPE:返回指定 key 的類型,string, list, set, zset, hash。時間複雜度 O(1)

CONFIG GET:獲得 Redis 某配置項的當前值,可以使用 * 通配符,時間複雜度 O(1)

CONFIG SET:爲 Redis 某個配置項設置新值,時間複雜度 O(1)

CONFIG REWRITE:讓 Redis 重新加載 redis.conf 中的配置
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章