【缓存中间件】redis 支持的数据类型
文章目錄
- 前言
- 一、字符串
- 二、哈希
- 三、 列表
- 四、集合
- 五、有序集合
- 六、位圖 Redis Bitmap
- 七、基數(shù)統(tǒng)計(jì) HyperLogLog
- 八、Geo 地理位置
- 九、Streams 流
- 應(yīng)用場景總結(jié)
前言
Redis 數(shù)據(jù)庫支持的數(shù)據(jù)類型。
- 最基本的5種
- 字符串(string)
- 哈希(hash)
- 列表(list)
- 集合(set)
- 有序集合(sorted set)
- 新版本
- 位圖 BitMap(2.2)
- 基數(shù)統(tǒng)計(jì) ( HyperLogLog) # 2.8.9新增
- Geo:地理位置信息儲(chǔ)存起來, 并對(duì)這些信息進(jìn)行操作 # 3.2新增
- 流(Stream)# 5.0新增
一、字符串
String 是一組字節(jié)。在 Redis 數(shù)據(jù)庫中,字符串是二進(jìn)制安全的。這意味著它們具有已知長度,并且不受任何特殊終止字符的影響。可以在一個(gè)字符串中存儲(chǔ)最多 512 兆字節(jié)的內(nèi)容。
例
使用 SET 命令在 name 鍵中存儲(chǔ)字符串 redis.com.cn,然后使用 GET 命令查詢 name。
在上面的例子中,SET 和 GET 是 Redis 命令,name 是 Redis 中使用的 key,abc 是存儲(chǔ)在 Redis 中的字符串值。
二、哈希
哈希是鍵值對(duì)的集合。在 Redis 中,哈希是字符串字段和字符串值之間的映射。因此,它們適合表示對(duì)象。
例
讓我們存儲(chǔ)一個(gè)用戶的對(duì)象,其中包含用戶的基本信息。
這里,HMSET 和 HGETALL 是 Redis 的命令,而 user:1 是鍵。
每個(gè)哈希可以存儲(chǔ)多達(dá) 2的32– 次方 1 個(gè)字段-值對(duì)。
三、 列表
Redis 列表定義為字符串列表,按插入順序排序。可以將元素添加到 Redis 列表的頭部或尾部。
例
lpush javatpoint java (integer) 1 lpush javatpoint java (integer) 1 lpush javatpoint java (integer) 1 lpush javatpoint java (integer) 1 lrange javatpoint 0 10 "cassandra" "mongodb" "sql" "java"列表的最大長度為 232 – 1 個(gè)元素(超過 40 億個(gè)元素)。
四、集合
集合(set)是 Redis 數(shù)據(jù)庫中的無序字符串集合。在 Redis 中,添加,刪除和查找的時(shí)間復(fù)雜度是 O(1)。
例
sadd tutoriallist redis (integer) 1 redis 127.0.0.1:6379> sadd tutoriallist sql (integer) 1 redis 127.0.0.1:6379> sadd tutoriallist postgresql (integer) 1 redis 127.0.0.1:6379> sadd tutoriallist postgresql (integer) 0 redis 127.0.0.1:6379> sadd tutoriallist postgresql (integer) 0 redis 127.0.0.1:6379> smembers tutoriallist 1) "redis" 2) "postgresql" 3) "sql"在上面的示例中,您可以看到 postgresql 被添加了三次,但由于該集的唯一屬性,它只添加一次。
集合中的最大成員數(shù)為 232-1 個(gè)元素(超過 40 億個(gè)元素)。
五、有序集合
Redis 有序集合類似于 Redis 集合,也是一組非重復(fù)的字符串集合。但是,排序集的每個(gè)成員都與一個(gè)分?jǐn)?shù)相關(guān)聯(lián),該分?jǐn)?shù)用于獲取從最小到最高分?jǐn)?shù)的有序排序集。雖然成員是獨(dú)特的,但可以重復(fù)分?jǐn)?shù)。
例
redis 127.0.0.1:6379> zadd tutoriallist 0 redis (integer) 1 redis 127.0.0.1:6379> zadd tutoriallist 0 sql (integer) 1 redis 127.0.0.1:6379> zadd tutoriallist 0 postgresql (integer) 1 redis 127.0.0.1:6379> zadd tutoriallist 0 postgresql (integer) 0 redis 127.0.0.1:6379> zadd tutoriallist 0 postgresql (integer) 0 redis 127.0.0.1:6379> ZRANGEBYSCORE tutoriallist 0 10 1) "postgresql" 2) "redis" 3) "sql"六、位圖 Redis Bitmap
Redis Bitmap 通過類似 map 結(jié)構(gòu)存放 0 或 1 ( bit 位 ) 作為值。
Redis Bitmap 可以用來統(tǒng)計(jì)狀態(tài),如日活是否瀏覽過某個(gè)東西。
Redis setbit 命令
Redis setbit 命令用于設(shè)置或者清除一個(gè) bit 位。
*Redis setbit 命令語法格式
SETBIT key offset value*范例
127.0.0.1:6379> setbit aaa:001 10001 1 # 返回操作之前的數(shù)值 (integer) 0 127.0.0.1:6379> setbit aaa:001 10002 2 # 如果值不是0或1就報(bào)錯(cuò) (error) ERR bit is not an integer or out of range 127.0.0.1:6379> setbit aaa:001 10002 0 (integer) 0 127.0.0.1:6379> setbit aaa:001 10003 1 (integer) 0七、基數(shù)統(tǒng)計(jì) HyperLogLog
Redis HyperLogLog 可以接受多個(gè)元素作為輸入,并給出輸入元素的基數(shù)估算值
-
基數(shù)
集合中不同元素的數(shù)量,比如 {‘a(chǎn)pple’, ‘banana’, ‘cherry’, ‘banana’, ‘a(chǎn)pple’} 的基數(shù)就是 3 -
估算值
算法給出的基數(shù)并不是精確的,可能會(huì)比實(shí)際稍微多一些或者稍微少一些,但會(huì)控制在合 理的范圍之內(nèi)
HyperLogLog 的優(yōu)點(diǎn)是:即使輸入元素的數(shù)量或者體積非常非常大,計(jì)算基數(shù)所需的空間總是固定的、并且是很小的。
在 Redis 里面,每個(gè) HyperLogLog 鍵只需要花費(fèi) 12 KB 內(nèi)存,就可以計(jì)算接近 264 個(gè)不同元素的基數(shù)。
這和計(jì)算基數(shù)時(shí),元素越多耗費(fèi)內(nèi)存就越多的集合形成鮮明對(duì)比。
因?yàn)?HyperLogLog 只會(huì)根據(jù)輸入元素來計(jì)算基數(shù),而不會(huì)儲(chǔ)存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個(gè)元素。
-
Redis PFADD 命令
Redis PFADD 命令將元素添加至 HyperLogLogRedis PFADD 命令語法格式
PFADD key element [element …] -
范例
八、Geo 地理位置
Redis 的 GEO 特性在 Redis 3.2 版本中推出, 這個(gè)功能可以將用戶給定的地理位置信息儲(chǔ)存起來, 并對(duì)這些信息進(jìn)行操作。GEO的數(shù)據(jù)結(jié)構(gòu)總共有六個(gè)命令:geoadd、geopos、geodist、georadius、georadiusbymember、gethash,GEO使用的是國際通用坐標(biāo)系WGS-84。
- 內(nèi)部編碼
但是,需要說明的是,Geo本身不是一種數(shù)據(jù)結(jié)構(gòu),它本質(zhì)上還是借助于Sorted Set(ZSET),并且使用GeoHash技術(shù)進(jìn)行填充。Redis中將經(jīng)緯度使用52位的整數(shù)進(jìn)行編碼,放進(jìn)zset中,score就是GeoHash的52位整數(shù)值。在使用Redis進(jìn)行Geo查詢時(shí),其內(nèi)部對(duì)應(yīng)的操作其實(shí)就是zset(skiplist)的操作。通過zset的score進(jìn)行排序就可以得到坐標(biāo)附近的其它元素,通過將score還原成坐標(biāo)值就可以得到元素的原始坐標(biāo)。
總之,Redis中處理這些地理位置坐標(biāo)點(diǎn)的思想是:二維平面坐標(biāo)點(diǎn) --> 一維整數(shù)編碼值 --> zset(score為編碼值) --> zrangebyrank(獲取score相近的元素)、zrangebyscore --> 通過score(整數(shù)編碼值)反解坐標(biāo)點(diǎn) --> 附近點(diǎn)的地理位置坐標(biāo)。
- 應(yīng)用場景
- 比如現(xiàn)在比較火的直播業(yè)務(wù),我們需要檢索附近的主播,那么GEO就可以很好的實(shí)現(xiàn)這個(gè)功能。
一是主播開播的時(shí)候?qū)懭胫鞑d的經(jīng)緯度,
二是主播關(guān)播的時(shí)候刪除主播Id元素,這樣就維護(hù)了一個(gè)具有位置信息的在線主播集合提供給線上檢索。 - 滴滴叫車:
- 記錄車位置:GEOADD cars:locations 116.034579 39.030452 33
- 用戶讀取附近的車:GEORADIUS cars:locations 116.054579 39.030452 5 km ASC COUNT 10
- 比如現(xiàn)在比較火的直播業(yè)務(wù),我們需要檢索附近的主播,那么GEO就可以很好的實(shí)現(xiàn)這個(gè)功能。
九、Streams 流
這是Redis5.0引入的全新數(shù)據(jù)結(jié)構(gòu),用一句話概括Streams就是Redis實(shí)現(xiàn)的內(nèi)存版kafka。支持多播的可持久化的消息隊(duì)列,用于實(shí)現(xiàn)發(fā)布訂閱功能,借鑒了 kafka 的設(shè)計(jì)。Redis Stream的結(jié)構(gòu)有一個(gè)消息鏈表,將所有加入的消息都串起來,每個(gè)消息都有一個(gè)唯一的ID和對(duì)應(yīng)的內(nèi)容。消息是持久化的,Redis重啟后,內(nèi)容還在。
每個(gè)Stream都有唯一的名稱,它就是Redis的key,在我們首次使用xadd指令追加消息時(shí)自動(dòng)創(chuàng)建。
每個(gè)Stream都可以掛多個(gè)消費(fèi)組,每個(gè)消費(fèi)組會(huì)有個(gè)游標(biāo)last_delivered_id在Stream數(shù)組之上往前移動(dòng),表示當(dāng)前消費(fèi)組已經(jīng)消費(fèi)到哪條消息了。每個(gè)消費(fèi)組都有一個(gè)Stream內(nèi)唯一的名稱,消費(fèi)組不會(huì)自動(dòng)創(chuàng)建,它需要單獨(dú)的指令xgroup create進(jìn)行創(chuàng)建,需要指定從Stream的某個(gè)消息ID開始消費(fèi),這個(gè)ID用來初始化last_delivered_id變量。
每個(gè)消費(fèi)組(Consumer Group)的狀態(tài)都是獨(dú)立的,相互不受影響。也就是說同一份Stream內(nèi)部的消息會(huì)被每個(gè)消費(fèi)組都消費(fèi)到。
同一個(gè)消費(fèi)組(Consumer Group)可以掛接多個(gè)消費(fèi)者(Consumer),這些消費(fèi)者之間是競爭關(guān)系,任意一個(gè)消費(fèi)者讀取了消息都會(huì)使游標(biāo)last_delivered_id往前移動(dòng)。每個(gè)消費(fèi)者者有一個(gè)組內(nèi)唯一名稱。
消費(fèi)者(Consumer)內(nèi)部會(huì)有個(gè)狀態(tài)變量pending_ids,它記錄了當(dāng)前已經(jīng)被客戶端讀取的消息,但是還沒有ack。如果客戶端沒有ack,這個(gè)變量里面的消息ID會(huì)越來越多,一旦某個(gè)消息被ack,它就開始減少。這個(gè)pending_ids變量在Redis官方被稱之為PEL,也就是Pending Entries List,這是一個(gè)很核心的數(shù)據(jù)結(jié)構(gòu),它用來確保客戶端至少消費(fèi)了消息一次,而不會(huì)在網(wǎng)絡(luò)傳輸?shù)闹型緛G失了沒處理。
- 消息ID:消息ID的形式是timestampInMillis-sequence,例如1527846880572-5,它表示當(dāng)前的消息在毫米時(shí)間戳1527846880572時(shí)產(chǎn)生,并且是該毫秒內(nèi)產(chǎn)生的第5條消息。消息ID可以由服務(wù)器自動(dòng)生成,也可以由客戶端自己指定,但是形式必須是整數(shù)-整數(shù),而且必須是后面加入的消息的ID要大于前面的消息ID。
- 消息內(nèi)容:消息內(nèi)容就是鍵值對(duì),形如hash結(jié)構(gòu)的鍵值對(duì),這沒什么特別之處。
內(nèi)部編碼
streams底層的數(shù)據(jù)結(jié)構(gòu)是radix tree:Radix Tree(基數(shù)樹) 事實(shí)上就幾乎相同是傳統(tǒng)的二叉樹。僅僅是在尋找方式上,以一個(gè)unsigned int類型數(shù)為例,利用這個(gè)數(shù)的每個(gè)比特位作為樹節(jié)點(diǎn)的推斷。能夠這樣說,比方一個(gè)數(shù)10001010101010110101010,那么依照Radix 樹的插入就是在根節(jié)點(diǎn),假設(shè)遇到0,就指向左節(jié)點(diǎn),假設(shè)遇到1就指向右節(jié)點(diǎn),在插入過程中構(gòu)造樹節(jié)點(diǎn),在刪除過程中刪除樹節(jié)點(diǎn)。如下是一個(gè)保存了7個(gè)單詞的Radix Tree:
應(yīng)用場景總結(jié)
實(shí)際上,所謂的應(yīng)用場景,其實(shí)就是合理的利用Redis本身的數(shù)據(jù)結(jié)構(gòu)的特性來完成相關(guān)業(yè)務(wù)功能,可參考我我之前寫的文章:學(xué)了redis不會(huì)實(shí)戰(zhàn)?看這篇就夠了
總結(jié)
以上是生活随笔為你收集整理的【缓存中间件】redis 支持的数据类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java SE 6.0实现高质量桌面集成
- 下一篇: 和兰花在一起