五種基本數(shù)據(jù)類型
String、Hash、List、Set和Zset。
1、String
等同于java中的,Map<String,String>string 是redis里面的最基本的數(shù)據(jù)類型,一個(gè)key對(duì)應(yīng)一個(gè)value。
- string 是二進(jìn)制安全的,可以把圖片和視頻文件保存在String中。
- string的最大內(nèi)存值 512M,即一個(gè)key或者value最大值是512M,官方說(shuō)可以存2.5億個(gè)key。
應(yīng)用場(chǎng)景:String是最常用的一種數(shù)據(jù)類型,普通的key/value存儲(chǔ)都可以歸為此類,如用戶信息,登錄信息和配置信息等;
實(shí)現(xiàn)方式:String在redis內(nèi)部存儲(chǔ)默認(rèn)就是一個(gè)字符串,被redisObject所引用,當(dāng)遇到incr、decr等操作(自增自減等原子操作)時(shí)會(huì)轉(zhuǎn)成數(shù)值型進(jìn)行計(jì)算,此時(shí)redisObject的encoding字段為int。
Redis雖然是用C語(yǔ)言寫的,但卻沒(méi)有直接用C語(yǔ)言的字符串,而是自己實(shí)現(xiàn)了一套字符串。目的就是為了提升速度,提升性能。Redis構(gòu)建了一個(gè)叫做簡(jiǎn)單動(dòng)態(tài)字符串(Simple Dynamic String),簡(jiǎn)稱SDS。
struct sdshdr{
// 記錄已使用長(zhǎng)度
int len;
// 記錄空閑未使用的長(zhǎng)度
int free;
// 字符數(shù)組
char[] buf;
};
Redis的字符串也會(huì)遵守C語(yǔ)言的字符串的實(shí)現(xiàn)規(guī)則,即最后一個(gè)字符為空字符。然而這個(gè)空字符不會(huì)被計(jì)算在len里頭。
- 因?yàn)橛辛藢?duì)字符串長(zhǎng)度定義len, 所以在處理字符串時(shí)候不會(huì)以零值字節(jié)(\0)為字符串結(jié)尾標(biāo)志.
- 二進(jìn)制安全就是輸入任何字節(jié)都能正確處理, 即使包含零值字節(jié).
Redis動(dòng)態(tài)擴(kuò)展步驟:
- 計(jì)算出大小是否足夠
- 開(kāi)辟空間至滿足所需大小
- 開(kāi)辟與已使用大小len相長(zhǎng)度同的空閑free空間(如果len < 1M),開(kāi)辟1M長(zhǎng)度的空閑free空間(如果len >= 1M)
Redis字符串的性能優(yōu)勢(shì)
- 快速獲取字符串長(zhǎng)度:直接返回len
- 避免緩沖區(qū)溢出:每次追加字符串時(shí)都會(huì)檢查空間是否夠用
- 降低空間分配次數(shù)提升內(nèi)存使用效率:(1)空間預(yù)分配;(2)惰性空間回收
常用命令:set/get/decr/incr/mget等,具體如下;
| 常用命令 | 命令 |
|---|---|
| 添加一對(duì)kv | set key value |
| 添加多對(duì)kv(可覆蓋) | mset key value key value…. |
| 添加多對(duì)kv(不可覆蓋,只要有一個(gè)已存在,全部取消) | msetnx key value key value…. |
| 獲取 | get value |
| 獲取多對(duì)kv | mget key key… |
| 刪除 | del key |
| 在末尾追加 | append key value |
| 查詢v的長(zhǎng)度 | strlen key |
| 給數(shù)值類型的v加/減1 | incr/decr key |
| 給數(shù)值類型增加/減少指定大小的值 | incrby/decrby key value |
| 獲取v的長(zhǎng)度 | getrange key |
| 在指定位置添加指定值(中間默認(rèn)用空格補(bǔ)全) | setrange key offset value |
| 添加指定生命周期的kv | setex key seconds value |
| 如果不存在則添加 | setnx key value |
| 獲取舊值,設(shè)置新值 | setget key value |
ps:計(jì)數(shù)器(字符串的內(nèi)容為整數(shù)的時(shí)候可以使用),如 set number 1。
補(bǔ)充:
127.0.0.1:6379> expire key 60 # 數(shù)據(jù)在 60s 后過(guò)期
(integer) 1
127.0.0.1:6379> setex key 60 value # 數(shù)據(jù)在 60s 后過(guò)期 (setex:[set] + [ex]pire)
OK
127.0.0.1:6379> ttl key # 查看數(shù)據(jù)還有多久過(guò)期
(integer) 56
2、Hash
等同于java中的:Map<String,Map<String,String>>,redis的hash是一個(gè)string類型的field和value的映射表,特別適合存儲(chǔ)對(duì)象。在redis中,hash因?yàn)槭且粋€(gè)集合,所以有兩層。第一層是key:hash集合value,第二層是hashkey:string value。所以判斷是否采用hash的時(shí)候可以參照有兩層key的設(shè)計(jì)來(lái)做參考。并且注意的是,設(shè)置過(guò)期時(shí)間只能在第一層的key上面設(shè)置。
- 使用hash,一般是有那種需要兩層key的應(yīng)用場(chǎng)景,也可以是‘刪除一個(gè)key可以刪除所有內(nèi)容’的場(chǎng)景。例如一個(gè)商品有很多規(guī)格,規(guī)格里面有不同的值。
- 或者查找所有商品的規(guī)格,查找商品id即可,具體的規(guī)格可以通過(guò)兩個(gè)key查找。
應(yīng)用場(chǎng)景:我們要存儲(chǔ)一個(gè)用戶信息對(duì)象數(shù)據(jù),其中包括用戶ID、用戶姓名、年齡和生日,通過(guò)用戶ID我們希望獲取該用戶的姓名或者年齡或者生日;
實(shí)現(xiàn)方式:Redis的Hash實(shí)際是內(nèi)部存儲(chǔ)的Value為一個(gè)HashMap,并提供了直接存取這個(gè)Map成員的接口。如,Key是用戶ID, value是一個(gè)Map。這個(gè)Map的key是成員的屬性名,value是屬性值。這樣對(duì)數(shù)據(jù)的修改和存取都可以直接通過(guò)其內(nèi)部Map的Key(Redis里稱內(nèi)部Map的key為field), 也就是通過(guò) key(用戶ID) + field(屬性標(biāo)簽) 就可以操作對(duì)應(yīng)屬性數(shù)據(jù)。當(dāng)前HashMap的實(shí)現(xiàn)有兩種方式:當(dāng)HashMap的成員比較少時(shí)Redis為了節(jié)省內(nèi)存會(huì)采用類似一維數(shù)組的方式來(lái)緊湊存儲(chǔ),而不會(huì)采用真正的HashMap結(jié)構(gòu),這時(shí)對(duì)應(yīng)的value的redisObject的encoding為zipmap,當(dāng)成員數(shù)量增大時(shí)會(huì)自動(dòng)轉(zhuǎn)成真正的HashMap,此時(shí)redisObject的encoding字段為int。
常用命令:hget/hset/hgetall等,具體如下:
| 作用 | 命令 |
|---|---|
| 添加單個(gè) | hset key field value |
| 獲取單個(gè) | hget key field |
| 一次性添加多個(gè)鍵值 | hmset key field1 value1 field2 value2 … |
| 一次性獲取多個(gè) | hmget |
| 獲取所有鍵值 | hgetall key |
| 刪除 | hdel |
| 獲取鍵值對(duì)的個(gè)數(shù) | hlen |
| 檢查是否包含某個(gè)字段 | hget key field |
| 查看所有key | hkeys |
| 給某個(gè)數(shù)值類型(否則報(bào)錯(cuò))的值增加指定整數(shù)值 | hincrby key field increment |
| 給某個(gè)數(shù)字類型值,增加指定浮點(diǎn)類型值 | hincrbyfloat key field increment |
| 如果不存在則添加 | hsetnx |
3、list
等同于java中的Map<String,List<String>>,list 底層是一個(gè)鏈表,在redis中,插入list中的值,只需要找到list的key即可,而不需要像hash一樣插入兩層的key。list是一種有序的、可重復(fù)的集合。
- redis的list是一個(gè)雙向鏈表(易于插入和刪除元素)。
- 它會(huì)按照我們插入的順序排序,然后我們可以從他的頭部添加/獲取元素,也可以從它的尾部添加/獲取元素,但帶來(lái)的額外的空間開(kāi)銷
應(yīng)用場(chǎng)景:Redis list的應(yīng)用場(chǎng)景非常多,也是Redis最重要的數(shù)據(jù)結(jié)構(gòu)之一,比如twitter的關(guān)注列表,粉絲列表等都可以用Redis的list結(jié)構(gòu)來(lái)實(shí)現(xiàn);
實(shí)現(xiàn)方式:Redis list的實(shí)現(xiàn)為一個(gè)雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過(guò)帶來(lái)了部分額外的內(nèi)存開(kāi)銷,Redis內(nèi)部的很多實(shí)現(xiàn),包括發(fā)送緩沖隊(duì)列等也都是用的這個(gè)數(shù)據(jù)結(jié)構(gòu)。

常用命令:lpush/rpush/lpop/rpop/lrange等,具體如下:
| 常用命令 | 命令 |
|---|---|
| 左壓棧 | lpush key v1 v2 v3 v4… |
| 右壓棧 | rpush key v1 v2 … |
| 查看里面的元素 | lrange key start offset |
| 左彈棧 | lpop key |
| 右彈棧 | rpop key |
| 按照索引查找 | lindex key index |
| 查看長(zhǎng)度 | llen key |
| 刪除幾個(gè)幾 | lrem key 數(shù)量 value |
| 指定開(kāi)始和結(jié)束的位置截取,再賦值給key | ltrim key start offset |
| 右出棧左壓棧,把resoure的左后一個(gè),壓倒dest的第一個(gè) | rpoplpush resource destination |
| 重置指定索引的值 | lset key index value |
| 在指定元素前/后插入指定元素 | linsert key before/after 值1 值2 |
性能總結(jié):
它是一個(gè)字符串鏈表,left、right都可以插入添加。
- 如果鍵不存在,創(chuàng)建新的鏈表。
- 如果鍵已經(jīng)存在,新增內(nèi)容。
- 值全部移除,key消失。
- 由于是鏈表,所以它對(duì)頭和尾操作的效率都極高。但是假如是對(duì)中間元素的操作,效率就可憐了。
4、Set
等同于java中的Map<String,Set<String>>,Set 是一種無(wú)序的,不能重復(fù)的集合。并且在redis中,只有一個(gè)key它的底層由hashTable實(shí)現(xiàn)的,天生去重。
應(yīng)用場(chǎng)景:Redis set對(duì)外提供的功能與list類似是一個(gè)列表的功能,特殊之處在于set是可以自動(dòng)去重的,當(dāng)你需要存儲(chǔ)一個(gè)列表數(shù)據(jù),又不希望出現(xiàn)重復(fù)數(shù)據(jù)時(shí),set是一個(gè)很好的選擇,并且set提供了判斷某個(gè)成員是否在一個(gè)set集合內(nèi)的重要接口,這個(gè)也是list所不能提供的;如保存一些標(biāo)簽的名字。標(biāo)簽的名字不可以重復(fù),順序是可以無(wú)序的。
實(shí)現(xiàn)方式:set 的內(nèi)部實(shí)現(xiàn)是一個(gè) value永遠(yuǎn)為null的HashMap,實(shí)際就是通過(guò)計(jì)算hash的方式來(lái)快速排重的,這也是set能提供判斷一個(gè)成員是否在集合內(nèi)的原因。
常用命令:sadd/spop/smembers/sunion等,具體如下:
| 常用命令 | 命令 |
|---|---|
| 添加值 | sadd key values |
| 查看值 | smembers key |
| 檢查集合是否有值 | sismember key value |
| 查看set集合里面的元素個(gè)數(shù) | scard key |
| 刪除集合中的指定元素 | srem key value |
| 隨機(jī)彈出某個(gè)元素 | srandmember key |
| 隨機(jī)出棧 | spop key |
| 把key1中的某個(gè)值賦值給key2 | smove SourceSet destSet member |
| 數(shù)學(xué)集合類 | 命令 |
|---|---|
| 差集 | sdiff |
| 交集 | sinte |
| 并集 | sunion |
5、Zset
ZSet(Sorted Set:有序集合) 每個(gè)元素都會(huì)關(guān)聯(lián)一個(gè)double類型的分?jǐn)?shù)score,分?jǐn)?shù)允許重復(fù),集合元素按照score排序(當(dāng)score相同的時(shí)候,會(huì)按照被插入的鍵的字典順序進(jìn)行排序),還可以通過(guò) score 的范圍來(lái)獲取元素的列表。
- set的值是 k1 v1 k2 v2
- zset的值 K1 score v1 k2 score v2
應(yīng)用場(chǎng)景:Redis sorted set的使用場(chǎng)景與set類似,區(qū)別是set不是自動(dòng)有序的,而sorted set可以通過(guò)用戶額外提供一個(gè)優(yōu)先級(jí)(score)的參數(shù)來(lái)為成員排序,并且是插入有序的,即自動(dòng)排序。當(dāng)你需要一個(gè)有序的并且不重復(fù)的集合列表,那么可以選擇sorted set數(shù)據(jù)結(jié)構(gòu),比如twitter 的public timeline可以以發(fā)表時(shí)間作為score來(lái)存儲(chǔ),這樣獲取時(shí)就是自動(dòng)按時(shí)間排好序的。
底層實(shí)現(xiàn):zset是Redis提供的一個(gè)非常特別的數(shù)據(jù)結(jié)構(gòu),常用作排行榜等功能,以用戶id為value,關(guān)注時(shí)間或者分?jǐn)?shù)作為score進(jìn)行排序。實(shí)現(xiàn)機(jī)制分別是zipList和skipList。規(guī)則如下:
zipList:滿足以下兩個(gè)條件
-
[score,value]鍵值對(duì)數(shù)量少于128個(gè); - 每個(gè)元素的長(zhǎng)度小于64字節(jié);
skipList:不滿足以上兩個(gè)條件時(shí)使用跳表、組合了hash和skipList
-
hash用來(lái)存儲(chǔ)value到score的映射,這樣就可以在O(1)時(shí)間內(nèi)找到value對(duì)應(yīng)的分?jǐn)?shù); -
skipList按照從小到大的順序存儲(chǔ)分?jǐn)?shù) -
skipList每個(gè)元素的值都是[socre,value]對(duì)
為什么用skiplist不用平衡樹(shù)?
主要從內(nèi)存占用、對(duì)范圍查找的支持和實(shí)現(xiàn)難易程度這三方面總結(jié)的原因。
- 內(nèi)存占用:skiplist比平衡樹(shù)更靈活一些。一般來(lái)說(shuō),平衡樹(shù)每個(gè)節(jié)點(diǎn)至少包含2個(gè)指針,而skiplist每個(gè)節(jié)點(diǎn)包含的指針數(shù)目平均為1/(1-p),具體取決于參數(shù)p的大小。如果像Redis里的實(shí)現(xiàn)一樣,取p=1/4,那么平均每個(gè)節(jié)點(diǎn)包含1.33個(gè)指針,比平衡樹(shù)更有優(yōu)勢(shì)。
- 范圍查找的支持:在做范圍查找的時(shí)候,平衡樹(shù)比skiplist操作要復(fù)雜。在平衡樹(shù)上,我們找到指定范圍的小值之后,還需要以中序遍歷的順序繼續(xù)尋找其它不超過(guò)大值的節(jié)點(diǎn)。如果不對(duì)平衡樹(shù)進(jìn)行一定的改造,這里的中序遍歷并不容易實(shí)現(xiàn)。而在skiplist上進(jìn)行范圍查找就非常簡(jiǎn)單,只需要在找到小值之后,對(duì)第1層鏈表進(jìn)行若干步的遍歷就可以實(shí)現(xiàn)。
- 實(shí)現(xiàn)難易程度:skiplist更加簡(jiǎn)單,平衡樹(shù)的插入和刪除操作可能引發(fā)子樹(shù)的調(diào)整,邏輯復(fù)雜,而skiplist的插入和刪除只需要修改相鄰節(jié)點(diǎn)的指針,操作簡(jiǎn)單又快速。
拓展:mysql為什么不用跳表?
常用命令:zadd/zrange/zrem/zcard等;
127.0.0.1:6379> zadd myZset 3.0 value1 # 添加元素到 sorted set 中 3.0 為權(quán)重
(integer) 1
127.0.0.1:6379> zadd myZset 2.0 value2 1.0 value3 # 一次添加多個(gè)元素
(integer) 2
127.0.0.1:6379> zcard myZset # 查看 sorted set 中的元素?cái)?shù)量
(integer) 3
127.0.0.1:6379> zscore myZset value1 # 查看某個(gè) value 的權(quán)重
"3"
127.0.0.1:6379> zrange myZset 0 -1 # 順序輸出某個(gè)范圍區(qū)間的元素,0 -1 表示輸出所有元素
1) "value3"
2) "value2"
3) "value1"
127.0.0.1:6379> zrange myZset 0 1 # 順序輸出某個(gè)范圍區(qū)間的元素,0 為 start 1 為 stop
1) "value3"
2) "value2"
127.0.0.1:6379> zrevrange myZset 0 1 # 逆序輸出某個(gè)范圍區(qū)間的元素,0 為 start 1 為 stop
1) "value1"
2) "value2"
三大特殊數(shù)據(jù)類型
1、geospatial
官網(wǎng)地址:https://redis.io/commands/geoadd
可以用來(lái)推算兩地之間的距離,方圓半徑內(nèi)的人。
關(guān)于經(jīng)度緯度的限制:https://www.redis.net.cn/order/3685.html
1# 添加三個(gè)城市
2127.0.0.1:16379[2]> geoadd china:city 116.40 39.99 beijing
3(integer) 1
4127.0.0.1:16379[2]> geoadd china:city 117.190 39.1255 tianjin
5(integer) 1
6127.0.0.1:16379[2]> geoadd china:city 120.36955 36.094 qingdao
7(integer) 1
8127.0.0.1:16379[2]>
9
10# 獲取指定key的經(jīng)度和緯度
11127.0.0.1:16379[2]> geopos china:city beijing
121) 1) "116.39999896287918091"
13 2) "39.99000043587556519"
14127.0.0.1:16379[2]>
15
16# 獲取兩個(gè)給定位置的距離
17127.0.0.1:16379[2]> geodist china:city beijing qingdao # 默認(rèn)單位為米
18"555465.2188"
19127.0.0.1:16379[2]> geodist china:city beijing qingdao km
20"555.4652"
21127.0.0.1:16379[2]> geodist china:city beijing qingdao m
22"555465.2188"
23127.0.0.1:16379[2]> geodist china:city beijing qingdao mi # 英里
24"345.1509"
25127.0.0.1:16379[2]> geodist china:city beijing qingdao ft # 英尺
26"1822392.4503"
27
28# 查找附近的人
29# 以給定的經(jīng)緯度為中心,找出某一半徑內(nèi)的元素
30127.0.0.1:16379[2]> georadius china:city 117.190 39.1255 200 km # 半徑為200km
311) "tianjin"
322) "beijing"
33127.0.0.1:16379[2]> georadius china:city 117.190 39.1255 200 km withdist # 指定顯示距離
341) 1) "tianjin"
35 2) "0.0001"
362) 1) "beijing"
37 2) "117.6221"
38127.0.0.1:16379[2]> georadius china:city 117.190 39.1255 200 km count 2 # 指定顯示2個(gè)結(jié)果
391) 1) "tianjin"
40 2) "0.0001"
412) 1) "beijing"
42 2) "117.6221"
43
44# 以指定的members為依據(jù),找到它指定范圍內(nèi)的元素
45127.0.0.1:16379[2]> GEORADIUSBYMEMBER china:city beijing 120 km
461) "beijing"
472) "tianjin"
48
49# 返回一個(gè)或者多個(gè)位置的11位長(zhǎng)度的hash串表示
50127.0.0.1:16379[2]> geohash china:city beijing
511) "wx4g2xzyss0"
52127.0.0.1:16379[2]> geohash china:city beijing tianjin
531) "wx4g2xzyss0"
542) "wwgqddx4sc0"
55
56# geo底層使用 zset 實(shí)現(xiàn)
57127.0.0.1:16379[2]> ZRANGE china:city 0 -1
581) "qingdao"
592) "tianjin"
603) "beijing"
61
62# 可以通過(guò)zrem刪除 geo添加的key中的member
63127.0.0.1:16379[2]> ZREM china:city beijing
64(integer) 1
65127.0.0.1:16379[2]> ZRANGE china:city 0 -1
661) "qingdao"
672) "tianjin"
2、Hyperloglog
一般我們使用Hyperloglog做基數(shù)統(tǒng)計(jì)。
什么是基數(shù)?就是一個(gè)集合中不重復(fù)的數(shù)的個(gè)數(shù)。
集合A:{1,3,5,7,9,7}
集合B:{1,3,5,7,9}
AB集合的基數(shù)都是5
應(yīng)用:統(tǒng)計(jì)網(wǎng)站的訪問(wèn)量(一個(gè)人訪問(wèn)網(wǎng)站很多次仍然算作一次)。
優(yōu)點(diǎn):占用的內(nèi)存是固定的,找2^64次方個(gè)數(shù)的基數(shù),只需要12KB內(nèi)存。
缺點(diǎn):有0.81%的錯(cuò)誤率,可以忽略不計(jì)
1# PFCOUNT 計(jì)算出來(lái)的數(shù)量就是Set的基數(shù)
2127.0.0.1:16379[2]> PFADD key4 q w e r q
3(integer) 1
4127.0.0.1:16379[2]> PFCOUNT key4
5(integer) 4
6
7# 添加key1和key對(duì)應(yīng)的多個(gè)值
8127.0.0.1:16379[2]> PFADD key1 q w e r
9(integer) 1
10
11# 統(tǒng)計(jì)key下有多少個(gè)值
12127.0.0.1:16379[2]> PFCOUNT key1
13(integer) 4
14
15# 添加key2和key對(duì)應(yīng)的多個(gè)值
16127.0.0.1:16379[2]> PFADD key2 a s d f
17(integer) 1
18
19# 合并多個(gè)key成為一個(gè)key
20127.0.0.1:16379[2]> PFMERGE key3 key1 key2
21OK
22127.0.0.1:16379[2]> PFCOUNT key3
23(integer) 8
3、Bitmap(*)
概述:bitmap 存儲(chǔ)的是連續(xù)的二進(jìn)制數(shù)字(0 和 1),通過(guò) bitmap, 只需要一個(gè) bit 位來(lái)表示某個(gè)元素對(duì)應(yīng)的值或者狀態(tài),key 就是對(duì)應(yīng)元素本身 。我們知道 8 個(gè) bit 可以組成一個(gè) byte,所以 bitmap 本身會(huì)極大的節(jié)省儲(chǔ)存空間。
應(yīng)用場(chǎng)景: 適合需要保存狀態(tài)信息(比如是否簽到、是否登錄...)并需要進(jìn)一步對(duì)這些信息進(jìn)行分析的場(chǎng)景。比如用戶簽到情況、活躍用戶情況、用戶行為統(tǒng)計(jì)(比如是否點(diǎn)贊過(guò)某個(gè)視頻)。
針對(duì)上面提到的一些場(chǎng)景,這里進(jìn)行進(jìn)一步說(shuō)明。
使用場(chǎng)景一:用戶行為分析 很多網(wǎng)站為了分析你的喜好,需要研究你點(diǎn)贊過(guò)的內(nèi)容。
# 記錄你喜歡過(guò) 001 號(hào)小姐姐
127.0.0.1:6379> setbit beauty_girl_001 uid 1
Copy to clipboardErrorCopied
使用場(chǎng)景二:統(tǒng)計(jì)活躍用戶
使用時(shí)間作為 key,然后用戶 ID 為 offset,如果當(dāng)日活躍過(guò)就設(shè)置為 1
那么我該如果計(jì)算某幾天/月/年的活躍用戶呢(暫且約定,統(tǒng)計(jì)時(shí)間內(nèi)只有有一天在線就稱為活躍),有請(qǐng)下一個(gè) redis 的命令
# 對(duì)一個(gè)或多個(gè)保存二進(jìn)制位的字符串 key 進(jìn)行位元操作,并將結(jié)果保存到 destkey 上。
# BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 這四種操作中的任意一種參數(shù)
BITOP operation destkey key [key ...]
Copy to clipboardErrorCopied
初始化數(shù)據(jù):
127.0.0.1:6379> setbit 20210308 1 1
(integer) 0
127.0.0.1:6379> setbit 20210308 2 1
(integer) 0
127.0.0.1:6379> setbit 20210309 1 1
(integer) 0
Copy to clipboardErrorCopied
統(tǒng)計(jì) 20210308~20210309 總活躍用戶數(shù): 1
127.0.0.1:6379> bitop and desk1 20210308 20210309
(integer) 1
127.0.0.1:6379> bitcount desk1
(integer) 1
Copy to clipboardErrorCopied
統(tǒng)計(jì) 20210308~20210309 在線活躍用戶數(shù): 2
127.0.0.1:6379> bitop or desk2 20210308 20210309
(integer) 1
127.0.0.1:6379> bitcount desk2
(integer) 2
Copy to clipboardErrorCopied
使用場(chǎng)景三:用戶在線狀態(tài)
對(duì)于獲取或者統(tǒng)計(jì)用戶在線狀態(tài),使用 bitmap 是一個(gè)節(jié)約空間效率又高的一種方法。
只需要一個(gè) key,然后用戶 ID 為 offset,如果在線就設(shè)置為 1,不在線就設(shè)置為 0。
總結(jié)
- 速度快,因?yàn)?strong>數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1)
- 支持豐富數(shù)據(jù)類型,支持string,list,set,sorted set(zset),hash
補(bǔ)充:
- 一個(gè)字符串類型的值能存儲(chǔ)最大容量是512M
- 其余類型元素最大存儲(chǔ)量為2^32 - 1,注意hash是鍵值對(duì)的個(gè)數(shù)
巨人的肩膀:
https://www.cnblogs.com/Small-sunshine/p/11687809.html
https://mp.weixin.qq.com/s/CMu7oXVIKp2s-PXTdMlimA