Redis 數據類型及應用場景

Redis 數據類型及應用場景

redis 特點

  • 所有數據存儲在內存中,高速讀寫
  • 提供豐富多樣的數據類型:string、 hash、 set、 zset、list、hyperloglog
  • 提供了 AOF 和 RDB 兩種數據的持久化保存方式,保證了 Redis 重啟後數據不丟失
  • Redis 的所有操作都是原子性的,還支持對幾個操作合併後的原子性操作,支持事務

通常我們都把數據存到關係型數據庫中,但為了提升應用的性能,我們應該把訪頻率高且不會經常變動的數據緩存到內存中。Redis 沒有像 MySQL 這類關係型數據庫那樣強大的查詢功能,需要考慮如何把關係型數據庫中的數據,合理的對應到緩存的 key-value 數據結構中。

設計 Redis Key

分段設計法

  • 使用冒號把 key 中要表達的多種含義分開表示,步驟如下:
  • 把表名轉化為 key 前綴
  • 主鍵名(或其他常用於搜索的字段)
  • 主鍵值
  • 要存儲的字段。

eg. 用戶表(user)

id name email 1 zj [email protected] 2 aa [email protected] 這個簡單的表可能經常會有這個的需求:>根據用戶 id 查詢用戶郵箱地址,可以選擇把郵箱地址這個數據存到 redis 中:

set user:id:1:email [email protected];
set user:id:2:email [email protected];

數據類型的應用場景

String類型

string 類型是 Redis 中最基本的數據類型,最常用的數據類型,甚至被很多玩家當成 redis 唯一的數據類型去使用。string 類型在 redis 中是二進制安全(binary safe)的,這意味著 string 值關心二進制的字符串,不關心具體格式,你可以用它存儲 json 格式或 JPEG 圖片格式的字符串。

數據模型

string 類型是基本的 Key-Value 結構,Key 是某個數據在 Redis 中的唯一標識,Value 是具體的數據。

key value name redis type string 應用場景

  1. 存儲 MySQL 中某個字段的值
  2. 把 key 設計為 表名:主鍵名:主鍵值:字段名
  3. eg.

set user:id:1:email [email protected]

  1. 存儲對象
  2. string 類型支持任何格式的字符串,應用最多的就是存儲 json 或其他對象格式化的字符串。(這種場景下推薦使用 hash 數據類型)

set user:id:1 '[{"id":1,"name":"zj","email":"[email protected]"},{"id":1,"name":"zj","email":"[email protected]"}]'

  1. 生成自增 id
  2. 當 redis 的 string 類型的值為整數形式時,redis 可以把它當做是整數一樣進行自增(incr)自減(decr)操作。由於 redis 所有的操作都是原子性的,所以不必擔心多客戶端連接時可能出現的事務問題。

hash類型

hash 類型很像一個關係型數據庫的數據表,hash 的 Key 是一個唯一值,Value 部分是一個 hashmap 的結構。

數據模型

假設有一張數據庫表如下:

id name type 1 redis hash 2 redis2 list 如果要用 redis 的 hash 結構存儲,數據模型如下:

Redis 數據類型及應用場景

hash.png

hash數據類型在存儲上述類型的數據時具有比 string 類型更靈活、更快的優勢,具體的說,使用 string 類型存儲,必然需要轉換和解析 json 格式的字符串,即便不需要轉換,在內存開銷方面,還是 hash 佔優勢。

應用場景

hash 類型十分適合存儲對象類數據,相對於在 string 中介紹的把對象轉化為 json 字符串存儲,hash 的結構可以任意添加或刪除‘字段名’,更加高效靈活。

hmset user:1 name zj email [email protected]

list類型

list 是按照插入順序排序的字符串鏈表,可以在頭部和尾部插入新的元素(雙向鏈表實現,兩端添加元素的時間複雜度為 O(1))。插入元素時,如果 key 不存在,redis 會為該 key 創建一個新的鏈表,如果鏈表中所有的元素都被移除,該 key 也會從 redis 中移除。

數據模型

Redis 數據類型及應用場景

list.png

常見操作時用 lpush 命令在 list 頭部插入元素, 用 rpop 命令在 list 尾取出數據。

應用場景

  1. 消息隊列
  2. redis 的 list 數據類型對於大部分使用者來說,是實現隊列服務的最經濟,最簡單的方式。
  3. “最新內容”
  4. 因為 list 結構的數據查詢兩端附近的數據性能非常好,所以適合一些需要獲取最新數據的場景,比如新聞類應用的 “最近新聞”。

優化建議

list 是鏈表結構,所有如果在頭部和尾部插入數據,性能會非常高,不受鏈表長度的影響;但如果在鏈表中插入數據,性能就會越來越差。

set類型

set 數據類型是一個集合(沒有排序,不重複),可以對 set 類型的數據進行添加、刪除、判斷是否存在等操作(時間複雜度是 O(1) )

  • set 集合不允許數據重複,如果添加的數據在 set 中已經存在,將只保留一份。
  • set 類型提供了多個 set 之間的聚合運算,如求交集、並集、補集,這些操作在 redis 內部完成,效率很高。

數據模型

Redis 數據類型及應用場景

set.png

應用場景

set 類型的特點是——不重複且無序的一組數據,並且具有豐富的計算功能,在一些特定的場景中可以高效的解決一般關係型數據庫不方便做的工作。

  1. “共同好友列表”
  2. 社交類應用中,獲取兩個人或多個人的共同好友,兩個人或多個人共同關注的微博這樣類似的功能,用 MySQL 的話操作很複雜,可以把每個人的好友 id 存到集合中,獲取共同好友的操作就可以簡單到一個取交集的命令就搞定。
// 這裡為了方便閱讀,把 id 替換成姓名
sadd user:wade james melo paul kobe
sadd user:james wade melo paul kobe
sadd user:paul wade james melo kobe
sadd user:melo wade james paul kobe
// 獲取 wade 和 james 的共同好友
sinter user:wade user:james
/* 輸出:
* 1) "kobe"
* 2) "paul"
* 3) "melo"
*/

// 獲取香蕉四兄弟的共同好友
sinter user:wade user:james user:paul user:melo
/* 輸出:
* 1) "kobe"
*/

/*
類似的需求還有很多 , 必須把每個標籤下的文章 id 存到集合中,可以很容易的求出幾個不同標籤下的共同文章;

把每個人的愛好存到集合中,可以很容易的求出幾個人的共同愛好。
*/

sorted set(zset)類型

在 set 的基礎上給集合中每個元素關聯了一個分數,往有序集合中插入數據時會自動根據這個分數排序。

應用場景

在集合類型的場景上加入排序就是有序集合的應用場景了。比如根據好友的“親密度”排序顯示好友列表。

// 用元素的分數(score)表示與好友的親密度
zadd user:kobe 80 james 90 wade 85 melo 90 paul
// 根據“親密度”給好友排序
zrevrange user:kobe 0 -1
/**
* 輸出:
* 1) "wade"
* 2) "paul"
* 3) "melo"
* 4) "james"
*/

// 增加好友的親密度
zincrby user:kobe 15 james
// 再次根據“親密度”給好友排序
zrevrange user:kobe 0 -1
/**
* 輸出:

* 1) "james"
* 2) "wade"
* 3) "paul"
* 2) "melo"
*/

//類似的需求還出現在根據文章的閱讀量或點贊量對文章列表排序

以上就是一些Redis常用的數據類型及應用場景,可以根據具體的業務需求使用相應的數據類型。

轉發+關注,私信我“書籍”即可獲取書籍資料


分享到:


相關文章: