Redis 數據類型
五種類型與類比java的模型
- string --> String
- hash --> Hashmap
- list --> LinkList
- set --> HashSet
- sorted_set --> TreeSet
String類型
redis 數據存儲格式
- redis自身是一個Map類型的存儲方式,其中所有的數據都是採用key:value的形式存儲
- 我們討論的數據類型指的是存儲的數據的類型,也就是value部分的類型,key部分永遠都是字符串
String基本信息
存儲的數據:單個數據,最簡單的數據存儲類型,也是最常用的數據存儲類型
存儲數據的格式:一個存儲空間保存一個數據
存儲內容:通常使用字符串,如果字符串以整數的形式展示,可以作爲數字操作使用(但是仍是字符串)
常用命令
- 添加/修改數據
set key value
- 獲取數據
get key
- 刪除數據
del key
- 添加/修改多個數據
mset key1 valueq key2 value2 …
- 獲取多個數據
mget key1 key2 …
- 獲取數據字符個數(字符串長度)
strlen key
- 追加信息到原始信息後部(如果原始信息存在就追加,否則新建)
append key value
String類型作爲數值時的增減
業務場景1
大型企業級應用中,分表操作是基本操作,使用多張表存儲同類型數據,但是對應的主鍵id必須保證統一性,不能重複。
Oracle數據庫具有sequence設定,可以解決該問題,但是MySQL數據庫並不具有類似的機制,那麼如何解決?
解決方案
- 設置數值數據增加指定範圍的值
incr key //自增1
incrby key increment //增加指定數值
incrbyfloat key increment //增加一個浮點數
- 設置數值數據減少指定範圍的值
decr key //自減1
decrby key increment //減少指定數值
String作爲數值操作時的注意事項
- string在redis內部存儲默認就是一個字符串,當遇到增減類操作incr,decr時會轉成數值型進行計算
- redis所有的操作都是原子性的,採用單線程處理所有業務,命令是一個一個執行的,因此無需考慮併發帶來的數據影響。
- 按數值進行操作的數據,如果原始數據不能轉成數值,或超過了redis數值上線範圍,將會報錯。9223372036854775807 (java中long型數據最大值,Long.MAX_VALUE)
String 數據時效性設置
業務場景2
場景一:“某某綜藝”,啓動海選投票,只能通過微信投票,每個微信號每4個小時只能投1票。
場景二:電商商家開啓熱門商品推薦,熱門商品不能一直處於熱門期,每種商品熱門期維持3天,3天后自動取消熱門
場景三:新聞網站會出現熱點新聞,熱點新聞最大的特徵是對時效性,如何自動控制熱點新聞的時效性
解決思路
給用戶設置一個唯一的id,併爲其設置一個有效時長,當時間已經超過設定時間後將id刪除。
解決方案
設置數據具有指定的聲明週期
redis 控制數據的生命週期,通過數據是否失效控制業務行爲,適用於所有具有時效性限定控制的操作:
setex key seconds value //增加、修改鍵值對併爲其設定生命週期
psetex key milliseconds value //功能與上面一直,秒的單位不同
String 類型的注意事項
數據操作成功與否的反饋
1、表示運行結果是否成功
(integer)0 –> false 失敗
(integer)1 –> true 成功
2、表示運行結果值
(integer)3 –> 3 3個
(integer)1 –> 1 1個
數據未獲取到
(nil)等同於null
String類型之高熱度數據訪問加速
業務場景3
主頁高頻訪問信息顯示控制,例如微博大V主頁顯示粉絲數與微博數量,這些數據就是熱度數據,不斷髮生變化,這些數據如何放入Redis?
解決方案
兩種實現方式:
-
在Redis中爲大V用戶設定用戶信息,以用戶主鍵和屬性值作爲key,後臺設定時間定時刷新即可。
- user: id :5765898790:focuss:3050
- user: id :5765898790:fans:117492300
- user: id :5765898790:blogs:117744
-
在Redis中以json格式存儲大V用戶,定時刷新。
- set user: id :5765898790 {id:5765898790,focuss:3050,fans:117492300,blogs:117744}
數據庫中的熱點數據key命名慣例:
hash類型
String類型存儲的困惑
對象類數據的存儲如果具有較爲頻繁的更新需求,操作會顯得笨重,存容易,改麻煩。
爲了區別與Redis中的鍵值對的稱呼,hash中的鍵成爲field,而key特徵Redis的鍵。
hash類型
新的存儲需求:對一系列存儲的數據進行編組,方便管理,典型應用存儲對象信息
需要的內存結構:一個存儲空間保存多少個鍵值對數據
hash類型:底層使用哈希表結構實現數據存儲
基本操作
- 添加/修改數據
hset key field value
- 獲取數據
hget key field
hgetall key
- 刪除數據
hdel key field1 [field2]
實例:
- 添加/修改多個數據
hmset key field1 value1 field2 calue2
- 獲取多個數據
hmget key field1 field2 …
- 獲取哈希表中字段的數量
hlen key
- 獲取哈希表中是否存在指定的字段
hexists key field
hash類型數據擴展操作
獲取哈希表中所有的字段名和字段值
hkeys key //字段名
hvals key //字段值
設置指定字段的數值數據增加指定範圍的值
hincrby key field increment //指定數值增長指定的數
hincrbyfloat key field increment
user1年齡增加2歲,再增加0.5歲:
hash類型數據操作的注意事項
- hash類型下的value只能存儲字符串,不允許存儲其他類型數據,不存在嵌套現象。如果數據未獲取到,對應的值爲(nil)
- 每個hash可以存儲232-1個鍵值對
- hash類型十分貼近對象的數據存儲形式,並且可以靈活添加刪除對象屬性。但hash設計不是爲了存儲大量對象的,切記不可濫用,更不可以將hash作爲對象列表使用
- hgetall操作可以獲取全部屬性,如果內部fiekd過多,遍歷整體數據效率就會很低,有可能成爲數據訪問瓶頸。
hash類型應用場景購物車
業務場景:電商網站購物車的設計與實現。
解決方案:
例如創建一個購物車:
當前僅僅是將數據存儲到redis中,並沒有起到加速的所用,因爲我們僅僅查詢到了用戶的id和商品的id,顯示的時候顯示的用戶名和商品的名稱,商品信息還需要二次查詢數據庫。
-
每條購物車中的商品記錄保存成兩條field
-
field1 專用於保存購買數量
1、命名格式:商品id:nums
2、保存數據:數值 -
field2 專用於保存購物車中顯示的信息,包含文字描述,圖片地址,所屬商家信息等等
1、命名格式:商品id:info
2、保存數據:json
但是出現很多用戶都將同一個商品假如購物車,就會出現大量的重複信息,例如商品信息重複:
因此我們可以將商品的信息單獨的保存成一個哈希。
創建數據,如果有則不再創建,如果沒有則創建
hsetnx key field value
Hash實現搶購,限購發放優惠券,激活碼等
解決方案
- 以商家id作爲key
- 將參與搶購的商品id作爲field
- 將參與搶購的商品數量作爲對應的value
- 搶購時使用降至的方式控制產品數量
list
數據存儲需求:存儲多個數據,並對數據進入存儲空間的順序進行區分
需要的存儲數據:一個存儲空間保存多個數據,且通過數據可以體現進入順序
list類型:保存多個數據,底層使用雙向鏈表存儲結構實現
- 添加/修改數據
lpush key value1 [value2] …
rpush key value1 [value2] …
- 獲取數據
lrange key start stop //獲取從左數第start到stop個元素,從0開始
lindex key index //查詢第i個元素
llen key //list的長度
- 獲取並移除數據
lpop key //獲取並刪除左邊第一個元素
rpop key //獲取並刪除右邊第一個元素
list 類型數組擴展操作
- 規定時間內獲取並移除數據
blpop key1 [key2] timeout
brpop key1 [key2] timeout
阻塞式獲取,在規定時間內獲取這個值,規定時間內如果還沒有的時候可以等,直到有值就可以獲取到獲取超時獲取爲空。
開兩個客戶端,一個設置15s內獲取list1中的值,此時list1位空一直等待(阻塞),在15秒內另一個客戶端存入到list1中數據,此時就被獲取到。
業務場景
微信朋友圈點贊,要求按照點贊順序顯示點贊好友信息。
如果取消點贊,移除對應好友信息。
解決方案
- 移除指定數據
lrem key count value //count爲移除的數量,value爲移除哪個值
list類型數據操作注意事項
- list 中保存的數據都是string類型的,數據總容量式是有限的,最多232-1個元素(4294967295)
- list具有索引的概念,但是操作數據時候通常以隊列的形式進行入隊出隊操作,或以棧的形式進入棧出棧的操作
- 獲取全部數據操作結束索引設置爲-1
- list 可以對數據進行分頁操作,通過第一頁的信息來自list,第2頁及更多的信息通過數據庫的形式加載
list類型應用場景
業務場景-最新消息的展示
- twitter、新浪微博、騰訊微博中個人用於的關注列表需要按照用戶的關注順序進行展示,粉絲列表需要將最近關注的粉絲列在前面
- 新聞、資訊類網站如何將最新的新聞或資訊按照發生的事件順序展示
- 企業運營過程中,系統將產生出大量的運營數據,如何保障墮胎服務器操作日誌的統一順序輸出?
解決方案
- 依賴list的數據具有順序的特徵對信息進行管理
- 使用隊列模型解決多路信息彙總合併的問題
- 使用棧模型解決最新消息的問題
Set
- 新的存儲需求:存儲大量的數據,在查詢方面提供更高的效率
- 需要的存儲結構:能夠保存大量的數據,搞笑的內部存儲機制,便於查詢
- set類型:與hash存儲結構完全相同,僅存儲鍵,不存儲值(nil),並且值式不允許重複的。也就是隻有鍵沒有值的hash
Set的基本操作
- 添加數據
sadd key menber1 [member2]
- 獲取全部數據
smembers key
- 刪除數據
srem key member1 [member2]
- 獲取集合數據總量
scard key
- 判斷集合中是否包含指定數據
sismember key member
set類型數據的擴展操作
業務場景-隨機操作數據
每位用戶首次使用進入頭條時候會設置3項愛好的內容,但是後期爲了增加用戶的活躍度,興趣點,必須讓用戶對其他信息類別逐漸產生興趣,增加客戶留存度,如何實現?
業務分析
- 系統分析出各個分類的最新或最熱點信息條目並組織成set集合
- 隨機挑選其中部分信息
- 配合用戶關注信息分類中的熱點信息組織展示的全信息集合
解決方案
- 隨機獲取集合中指定數量的數據
srandmember key [count]
- 隨機獲取集合中的某個數據並將該數據移出集合
spop key
redis應用於隨機推薦類信息檢索,例如熱點歌單推薦,熱點新聞推薦,熱點旅遊線路,應用APP推薦,大V推薦等。
業務場景-共同好友
例如:
解決方案
- 求兩個集合的交、並、差集
sinter key1 [key2] //交集
sunion key1 [key2] //並集
sdiff key1 [key2] //差集(key1有但是key2沒有的)
- 求兩個集合的交、並、差集並存儲到指定集合中
sinterstore destination key1 [key2]
sunionstore destination key1 [key2]
sdiffstore destination key1 [key2]
- 將指定數據從原始集合移動到目標集合中
smove source destination member
redis應用於同類信息的關聯搜索,二度關聯搜索,深度關聯搜索
- 顯示共同關注(一度)
- 顯示共同好友(一度)
- 由用戶A出發,獲取到好友用戶B的好友信息列表(一度)
- 由用戶A出發,獲取到好友用戶B的購物清單列表(二度)
- 由用戶A出發,獲取到好友用戶B的遊戲充值列表(二度)
Set類型數據操作的注意事項
set類型不允許數據重複,如果添加的數據在set中已經存在,將只保留一份
set雖然與hash的存儲結構相同,但是無法啓用hash中存儲值的空間
業務場景-同類型不重複數據的合併操作
解決方案
依賴set集合數據不重複的特徵,依賴set集合hash存儲結構特徵完成數據過濾與快速查詢
- 根據用戶id獲取用戶所有角色
- 根據用戶所有角色獲取用戶所有操作權限放入set集合
- 根據用戶所有覺得獲取用戶所有數據全選放入set集合
兩種方法,其中第二種耦合度太高:
set業務場景-訪問量統計去重
解決方案
針對不同的統計類型有不同的數據存儲方式:
- 利用set集合的數據去重特徵,記錄各種訪問數據
- 建立string類型數據,利用incr統計日訪問量(PV)
- 建立set模型,記錄不同cookie數量(UV)
- 建立set模型,記錄不用IP數量(IP)
set業務場景-黑白名單
解決方案
- 基於經營戰略設定問題用戶發現、鑑別規則
- 週期性更行滿足規則的用戶黑名單,加入set集合
- 用戶行爲信息達到後與黑名單進行比比對,確認行爲去向
- 黑名單過濾IP地址:應用於開放遊客訪問權限的信息源
- 黑名單過濾設備信息:應用於限定訪問設備的信息源
- 黑名單過濾用戶:應用於基於訪問權限的信息源
sorted_set類型
- 新的存儲需求:根據排序有利於數據的有效顯示,需要提供一種可以根據自身特徵進行排序的方式。
- 需要的存儲結構:新的存儲模型,可以保存可排序的數據。
- sorted_set類型:在set的存儲結構基礎上添加可排序字段。
score只存儲其順序。
sorted_set類型數據的基本操作
- 添加數據
zadd key score1 member1 [score2 member2]
- 獲取全部數據
zrange key start stop [WITHSCORES]//按照從小到大的順序,加上WITHSCORES,就會帶上scores一起顯示
zrevrange key start stop [WITHSCORES]//按照從大到小的順序
- 刪除數據
zrem key member [member …]
- 按條件獲取數據
//查詢scores在某個範圍內的值
zrangebyscore key min max [WITHSCORES] [LIMIT]
//查詢key某個索引範圍內的值
zrevrangebyscore key max min [WITHSCORES]
- 條件刪除
zremrangebyrank key start stop
zremrangebyscore key min max
注意:
- min與max用於限定搜索查詢的條件
- start與stop用於限定查詢範圍,作用於索引,表示開始和結束索引
- offset與count用於限定查詢範圍,作用於查詢結果,表示開始位置和數據總量
獲取集合數據總量
zcard key //獲取總量
zcount key min max //獲取某一個範圍的總量
- 集合交、並存儲操作
zinterstore destination numkeys key [key …] //求和
zunionstore destination numkeys key [key …]
sorted_set 類型數據的擴展操作
業務場景- 建立排序依據
解決方案
- 獲取數據對應的索引(排名)
zrank key member //正數第幾位
zrevrank key member //倒數第幾位
- score 值獲取與修改
zscore key member //獲取
zincrby key increment member //score遞增 increment
sorted_set 類型數據操作的注意事項
- score 保存的數據存儲空間是64位
- score保存的數據也可以是一個雙精度的double值,基於雙精度浮點數的特徵,可能會丟失精度,使用時侯要慎重
- sorted_set底層存儲還是基於set結構的,因此數據不能重複,如果重複添加相同的數據,score值將被反覆覆蓋,保留最後一次修改的結果
業務場景-會員短期體驗之過期失效
解決方案
- 對於基於時間線限定的任務處理,將處理時間記錄爲score值,利用排序功能區分處理的先後順序
- 記錄下一個要處理的事件,當對比系統時間發現當然仍後到期後移除redis中的記錄,並記錄下一個要處理的時間
- 當新任務加入時,判定並更新當前下一個要處理的任務時間
- 爲提升sorted_set的性能,通常將任務根據特徵存儲成若干個sorted_set.例如1小時內,1天內,年度等,操作時逐漸提升,將即將操作的若干個任務納入到1小時內處理隊列中
- time命令獲取當前系統時間
數據類型實踐案例
按次調用-計數器
如何實現這個每分鐘只能調用10次呢?
解決方案
- 設計計數器,記錄調用次數,用於控制業務執行次數。以用戶id作爲key,使用此時作爲value
- 在調用前獲取次數,判斷是否超過限定次數,不超過次數的情況下,每次調用計數+1,業務調用失敗,不遞增
- 爲了計數器設置生命週期爲指定週期,例如10次/分鐘,自動清空週期內使用次數。
解決方案改良
利用可以存儲的最大值是9223372036854775807,超過這個值就會拋出異常的特性。假如一分鐘只能訪問5次,可以將初始值設置爲9223372036854775802,每次訪問都加1,訪問5次後這個數就會溢出異常。
微信會話
解決方案
- 依賴list的數據具有順序的特徵對消息進行管理,將list結構作爲棧使用
對指定與普通會話分別創建獨立的list分別管理 - 當某個list中接收到用戶消息後,將消息發送方的id從list的一側加入list(此處設定左側)
- 多個相同id發出的消息反覆入棧會出現問題,在入棧之前無論是否具有當前id對應得消息,先刪除對應id
- 推送消息時先推送頂置會話list,再推送普通會話list,推送完成的list清除所有數據
- 消息的數量,也就是微信用戶對話數量採用計數器的思想另行記錄,伴隨list操作同步更新