Redis學習筆記—資料型別
- String
string是redis最基本的資料型別,他是二進位制安全的---意味著string可以包含任何資料,jpg圖片序列化物件等等。一個string的value最大可以是512M(10^6bytes)
set key value //設定K-V,若存在則覆蓋原值 keys * //獲取所有key setex key <過期時間> <value> getset <key> <value> //設定新值返回舊值 ------ 以下均為原子命令 incr k //v為數字是+1,下同 incrby num //增加指定數量 decr k //減操作 mset k1 v1 k2 v2... //同時設定多個值 mget k1 k2 ... getrange //根據範圍獲取值,下面是設定值 setrange
string的的資料結構為簡單的動態字串,是可修改的字串。實現上類似golang的byte切片,預分配空間來減少記憶體的頻繁分配。len < 1M時擴容是翻倍,超過後每次增加1M,注意最大長度為512M。
-
List
redis的list是簡單的字串列表,按照插入順序排序,可以新增一個元素到頭或者尾,底層實際是個雙向連結串列。lpush/rpush key //左右放入 lpop/rpop key //取值k也消亡 rpoplpush key1 key2 //從k1右邊取3,放入k2左邊 lrange key start end linsert key BEFORE|AFTER pivot element lrem key count element //從左邊刪除count數量v lset key index element //覆蓋index的v
List的資料結構是quicklist。在元素較少的情況下會使用一塊連續記憶體儲存,結構是ziplist,當資料較多時用多個雙向指標將ziplist串起來。
普通連結串列的附加指標空間太大比較浪費,上述結構可以節省空間。
-
Set
set是string型別的無序集合,與list類似的列表功能,不過可以自動去重(類似cpp的set)。set提供了判斷某個成員是否在內的一個介面(sismemebr)這是list不具備的。底層是一個value為null的雜湊表。sadd key member [member ...] //將一個或多個成員加入集合key smembers key //取出集合key全部元素 sismember key value //判斷集合key是否有value scard key //判斷集合元素個數 srem key v1, v2... //刪除集合k中元素 spop key //集合中隨機彈出一個元素 srandmember key n //隨機取出n個值,但不會刪除 smove source destination member //把集合的一個v移動到另一集合 sinter //取交併差集,後面的key可以是多個 sunion sdiff
set底層結構是dict字典,字典是用hash表實現的。與java的hashset類似,所有的value都指向同一個內部值。
-
Hash
redis hash是一個string型別的filed-value,適合儲存物件類似java的Map<String,Object>
hset key field value [field value ...] //給key中field賦值 hmset key field value [field value ...] //批量設定hash hget key field //取值 hexists key field //判斷field是否存在 hkeys key //列出所有field hvals key //列出所有value hincrby key field increment //給field對應值+1,-1 hsetnx key field value //當field不存在設定field-value,不會覆蓋
當F-V長度短且數量較少使用ziplist,否則使用hashtable
-
Zset-有序集合
在基本集合基礎上給每個成員增加了score,用來增序排序,元素唯一但是score可以重複。訪問Zset集合的中間成員也是很快的因此可以用來作為一個沒有重複成員的只能列表。
zadd key score1 valuel... //新增元素 zrange key start stop [WITHSCORES] //返回指定順序區間元素 zreeange key start stop [WITHSCORES] //同上逆順 zrangebyscore key min max [WITHSCORES] //返回score區間的元素 zrevrangebyscore key max min [WITHSCORES] //從大到小排序 zincrby key increment member //為元素增加制定的值score zrem key member [member ...] //刪除制定元素 zcount key min max //統計區間內元素個數 zrank key member //返回元素排名
Zset底層使用了兩個資料結構
- Hash : hash用來關聯元素value和score保證value唯一性,可以通過V找到S,field是value,value是score
- 跳躍表:用來給V排序,根據score的範圍獲取元素列表
-
Bitmaps
Bitmaps本身不是一種資料型別, 實際上它就是字串(key-value) , 但是它可以對字串的位進行操作。 可以把Bitmaps想象成一個以位為單位的陣列, 陣列的每個單元只能儲存0和1, 陣列的下標在Bitmaps中叫做偏移量。在第一次初始化Bitmaps時, 假如偏移量非常大, 那麼整個初始化過程執行會比較慢, 可能會造成Redis的阻塞setbit key offset value //設定Bitmaps中某個偏移量的值 getbit key offset //獲取Bitmaps中某個偏移量的值 bitcount key [start end] [BYTE|BIT] //統計字串從start位元組到end位元組位元值為1的數量 bitop and(or/not/xor) destkey key… //位運算and,or,not,xor結果儲存在destkey
注意:redis的setbit設定或清除的是bit位置,而bitcount計算的是預設是byte位置,可選bit
考慮如下場景:
每個獨立使用者是否訪問過網站存放在Bitmaps中, 將訪問的使用者記做1, 沒有訪問的使用者記做0, 用偏移量作為使用者的id。如果活躍使用者數量非常龐大的情況下Bitmap的空間效率和set相比會高很多,尤其是隨著時間推移節省的記憶體還是非常可觀的。但是活躍使用者較少的情況下Bitmap的大多數位是0則會造成很多浪費,空間利用率可能反而不如set。
-
HyperLogLog
獨立ip數、搜尋記錄數等需要去重和計數這種求集合中不重複元素個數的問題稱為基數問題。解決基數問題有很多種方案通常有:
-
資料儲存在MySQL表中,使用distinct count計算不重複個數
-
使用Redis提供的hash、set、bitmaps等資料結構來處理
以上的方案結果精確,但隨著資料不斷增加,導致佔用空間越來越大,對於非常大的資料集是不切實際的。
HyperLogLog的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定且很小。每個HyperLogLog 鍵只需要花費 12 KB記憶體,就可以計算接近 2^64 個不同元素的基數。這和計算基數時,元素越多耗費記憶體就越多的集合形成鮮明對比。因為HyperLogLog只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以HyperLogLog不能像集合那樣,返回輸入的各個元素
pfadd <key><element> [element ...] //新增指定元素到 HyperLogLog 中 pfcount<key> [key ...] //計算HLL的近似基數 pfmerge<destkey><sourcekey> [sourcekey ...] //將一個或多個HLL合併後的結果儲存在另一個HLL中
-
-
Geospatial
redis基於該型別,提供了經緯度設定,查詢,範圍查詢,距離查詢,經緯度Hash等常見操作。兩極無法直接新增,一般會下載城市資料,直接匯入
geoadd <key><longitude><latitude><member> [longitude latitude member...] //新增地理位置(經度,緯度,名稱) geopos <key><member> [member...] //獲得指定地區的座標值 geodist <key><member1><member2> [m|km|ft|mi ] //獲取兩個位置之間的直線距離 georadius<key>< longitude><latitude>radius m|km|ft|mi //以給定的經緯度為中心,找出某一半徑內的元素