1. 程式人生 > >《閒扯Redis九》Redis五種資料型別之Set型

《閒扯Redis九》Redis五種資料型別之Set型

------ ## 一、前言 >**Redis** 提供了5種資料型別:String(字串)、Hash(雜湊)、List(列表)、Set(集合)、Zset(有序集合),理解每種資料型別的特點對於redis的開發和運維非常重要。

原文解析

![Redis五種資料型別][1] **Redis** 中的 Set 是我們經常使用到的一種資料型別,根據使用方式的不同,可以應用到很多場景中。 ## 二、底層實現  集合物件的編碼可以是 intset 或者 hashtable 。  intset 編碼的集合物件使用整數集合作為底層實現, 集合物件包含的所有元素都被儲存在整數集合裡面。  舉個例子, 以下程式碼將建立一個如圖 8-12 所示的 intset 編碼集合物件: ```java redis>
SADD numbers 1 3 5 (integer) 3 ``` 結構圖 8-12:
![Redis五種資料型別][2]
 另一方面, hashtable 編碼的集合物件使用字典作為底層實現, 字典的每個鍵都是一個字串物件, 每個字串物件包含了一個集合元素, 而字典的值則全部被設定為 NULL 。 舉個例子, 以下程式碼將建立一個如圖 8-13 所示的 hashtable 編碼集合物件: ```java redis> SADD fruits "apple" "banana" "cherry" (integer) 3 ``` 結構圖 8-13:
![Redis五種資料型別][3]
## 三、編碼轉換  當集合物件可以同時滿足以下兩個條件時, 物件使用 intset 編碼: >1.集合物件儲存的所有元素都是整數值; >2.集合物件儲存的元素數量不超過 512 個;  不能滿足這兩個條件的集合物件需要使用 hashtable 編碼。 **注意 :** 第二個條件的上限值是可以修改的, 具體請看配置檔案中關於 set-max-intset-entries 選項的說明。對於使用 intset 編碼的集合物件來說, 當使用 intset 編碼所需的兩個條件的任意一個不能被滿足時, 物件的編碼轉換操作就會被執行: 原本儲存在整數集合中的所有元素都會被轉移並儲存到字典裡面, 並且物件的編碼也會從 intset 變為 hashtable。  舉個例子, 以下程式碼建立了一個只包含整數元素的集合物件, 該物件的編碼為 intset : ```java redis>
SADD numbers 1 3 5 (integer) 3 redis> OBJECT ENCODING numbers "intset" ```  不過, 只要我們向這個只包含整數元素的集合物件新增一個字串元素,集合物件的編碼轉移操作就會被執行 ```java redis> SADD numbers "seven" (integer) 1 redis> OBJECT ENCODING numbers "hashtable" ```  除此之外, 如果我們建立一個包含 512 個整數元素的集合物件, 那麼物件的編碼應該會是 intset : ```java redis> EVAL "for i=1, 512 do redis.call('SADD', KEYS[1], i) end" 1 integers (nil) redis> SCARD integers (integer) 512 redis> OBJECT ENCODING integers "intset" ```  但是, 只要我們再向集合新增一個新的整數元素, 使得這個集合的元素數量變成 513 , 那麼物件的編碼轉換操作就會被執行: ```java redis> SADD integers 10086 (integer) 1 redis> SCARD integers (integer) 513 redis> OBJECT ENCODING integers "hashtable" ``` ## 四、命令實現  因為集合鍵的值為集合物件, 所以用於集合鍵的所有命令都是針對集合物件來構建的, 以下表格列出了其中一部分集合鍵命令, 以及這些命令在不同編碼的集合物件下的實現方法。 |命令 |intset 編碼的實現方法 |hashtable 編碼的實現方法| | -------- | :---- | :---- | |SADD |呼叫 intsetAdd 函式, 將所有新元素新增到整數集合裡面。 |呼叫 dictAdd , 以新元素為鍵, NULL 為值, 將鍵值對新增到字典裡面。| |SCARD |呼叫 intsetLen 函式, 返回整數集合所包含的元素數量, 這個數量就是集合物件所包含的元素數量。 |呼叫 dictSize 函式, 返回字典所包含的鍵值對數量, 這個數量就是集合物件所包含的元素數量。| |SISMEMBER |呼叫 intsetFind 函式, 在整數集合中查詢給定的元素, 如果找到了說明元素存在於集合, 沒找到則說明元素不存在於集合。 |呼叫 dictFind 函式, 在字典的鍵中查詢給定的元素, 如果找到了說明元素存在於集合, 沒找到則說明元素不存在於集合。| |SMEMBERS |遍歷整個整數集合, 使用 intsetGet 函式返回集合元素。 |遍歷整個字典, 使用 dictGetKey 函式返回字典的鍵作為集合元素。| |SRANDMEMBER |呼叫 intsetRandom 函式, 從整數集合中隨機返回一個元素。 |呼叫 dictGetRandomKey 函式, 從字典中隨機返回一個字典鍵。| |SPOP |呼叫 intsetRandom 函式, 從整數集合中隨機取出一個元素, 在將這個隨機元素返回給客戶端之後, 呼叫 intsetRemove 函式, 將隨機元素從整數集合中刪除掉。 |呼叫 dictGetRandomKey 函式, 從字典中隨機取出一個字典鍵, 在將這個隨機字典鍵的值返回給客戶端之後, 呼叫dictDelete 函式, 從字典中刪除隨機字典鍵所對應的鍵值對。| |SREM |呼叫 intsetRemove 函式, 從整數集合中刪除所有給定的元素。 |呼叫 dictDelete 函式, 從字典中刪除所有鍵為給定元素的鍵值對。| ## 五、應用場景 ### 1.抽獎 ```java 抽獎 1)使用者參與抽獎:SADD order 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 2)檢視所有參與抽獎的人:SMEMBERS order 3)重複抽獎每次抽取兩人:SMEMBERS order 2 4)不重複抽獎,三等獎3人,二等獎2人,一等獎1人 SPOP order 3 SPOP order 2 SPOP order 1 ``` ### 2.點贊、收藏、標籤 ```java 點贊、收藏、標籤 1)點讚的人:SADD like:1 1001 1002 1003 1004 1005 2)取消點贊:SREM like:1 1002 3)檢查使用者是否點贊過: SISMEMBER like:1 1002 SISMEMBER like:1 1005 4)獲取點贊人員列表:SMEMBERS like:1 5)獲取點贊總人數:SCARD like:1 ``` ### 3.關注模型 ```java redis> SADD wangwu zhangsan lisi zhaoliu haoba (integer) 4 redis> SADD zhangsan lisi wangwu sijiu (integer) 3 redis> SADD lisi zhaoliu zhangsan qinshi (integer) 3 redis> SINTER wangwu zhangsan 1) "lisi" redis> SISMEMBER zhangsan lisi (integer) 1 redis> SISMEMBER lisi zhangsan (integer) 1 redis> SISMEMBER zhaoliu zhangsan (integer) 0 redis> SISMEMBER haoba zhangsan (integer) 0 redis> SDIFF zhangsan wangwu 1) "sijiu" 2) "wangwu" redis> SDIFF lisi wangwu 1) "qinshi" ``` ## 六、要點總結 >(1)集合物件的編碼可以是 intset 或者 hashtable 。 >(2)intset 編碼的集合物件使用整數集合作為底層實現。 >(3)hashtable 編碼的集合物件使用字典作為底層實現。 >(4)intset 與 hashtable 編碼之間,符合條件的情況下,可以轉換。 over
![Redis五種資料型別][4]
[1]: http://www.yund.tech/yund-cms//sys/common/view/files/20200402/list-2.png [2]: http://www.yund.tech/yund-cms//sys/common/view/files/20200402/redis9-12.png [3]: http://www.yund.tech/yund-cms//sys/common/view/files/20200402/redis9-13.png [4]: http://www.yund.tech/yund-cms//sys/common/view/files/20200618/gzhmp.png