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