1. 程式人生 > >redis的5種資料結構和應用場景介紹

redis的5種資料結構和應用場景介紹

       在服務端為了減輕高併發下資料庫的訪問壓力,經常要應用快取。redis和memcached都可以作為快取系統使用,redis與memcached一樣,為了保證效率,資料都是快取在記憶體中,讀寫的效能差距不大。區別的是redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了master-slave(主從)同步。而且相比memcache,redis還支援事務操作和多種儲存結構,在分散式叢集的架構下,redis的擴充套件性更強。

       認識redis,最基本就是了解它支援儲存的資料結構和特性,這樣才能更好的理解它的操作命令和應用場景。基於redis的廣泛應用,今天的小課堂就和大家一起認識一下redis中基本的5種資料結構。

      redis的簡單認識

      作為快取工具時的使用,我們經常將一些結構化的資訊打包成集合,序列化後儲存為一個字串的值,比如使用者的暱稱、年齡、性別、積分等。這時候在讀取,需要將字串取出來,然後進行反序列化。如果修改某一項的值,需要再序列化成字串儲存回去。簡單修改一個屬性就幹這麼多事情,消耗必定是很大的,也不適用於一些可能併發操作的場合。因此我們可以例如redis支援資料型別的特性,根據業務用Redis直接儲存資料,實現功能。

      redis是一個key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)和zset(有序集合)、Hash(字典)。

      這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。

     如果你是Redis中高階使用者,還需要加上下面幾種資料結構:

     HyperLogLog(基數): 比如資料集 {1, 3, 5, 7, 5, 7, 8}, 那麼這個資料集的基數集為 {1, 3, 5 ,7, 8}, 基數(不重複元素)為5。 基數估計就是在誤差可接受的範圍內,快速計算基數。

    GEO 特性在 Redis 3.2 版本推出, 這個功能可以將使用者給定的地理位置資訊儲存起來, 並對這些資訊進行操作(空間資料的儲存格式,點線面關係)。

    Pub/Sub (釋出訂閱)是一種訊息通訊模式:傳送者(pub)傳送訊息,訂閱者(sub)接收訊息。

Redis常見資料結構使用場景

1. String

常用命令:  set,get,decr,incr,mget 等。

String資料結構是簡單的key-value型別,value其實不僅可以是String,也可以是數字。 常規key-value快取應用; 常規計數:微博數,粉絲數等。

我們在nginx做負載均衡的時候,如果是基於權重的分配方式,切換web伺服器時,會導致使用者的session資訊丟失我們可以將它儲存在redis種。

2.Hash

常用命令: hget,hset,hgetall 等。

        redis中的雜湊結構就如同java中的map一樣,Hash是一個string型別的field和value的對映表,hash特別適合用於儲存物件。 Redis 的 Hash 結構可以使你像在資料庫中 Update 一個屬性一樣只修改某一項屬性值。它的使用方法就像它的別名字典,通過對應的字典名(key)和詞條名(field)查詢內容(value)

      比如我們可以Hash資料結構來儲存使用者資訊,商品資訊等等。例如修真院的首頁的職業資訊,只是簡單的資訊集合,我們可以直接將它儲存到redis中,在讀取的過程中就不用序列化物件,直接操作。

3.List

常用命令: lpush,rpush,lpop,rpop,lrange等

list就是連結串列,Redis list的應用場景非常多,也是Redis最重要的資料結構之一,比如微博的關注列表,粉絲列表,最新訊息排行等功能都可以用Redis的list結構來實現。

Redis list的實現為一個雙向連結串列,即可以支援反向查詢和遍歷,更方便操作,不過帶來了部分額外的記憶體開銷。

4.Set

常用命令:sadd,spop,smembers,sunion 等

set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的。 當你需要儲存一個列表資料,又不希望出現重複資料時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的。

1.共同好友、二度好友2.利用唯一性,可以統計訪問網站的所有獨立 IP3.好友推薦的時候,根據 tag 求交集,大於某個 threshold 就可以推薦

5.Sorted Set

常用命令: zadd,zrange,zrem,zcard等

和set相比,sorted set增加了一個權重引數score,使得集合中的元素能夠按score進行有序排列。

舉例: 在直播系統中,實時排行資訊包含直播間線上使用者列表,各種禮物排行榜,彈幕訊息(可以理解為按訊息維度的訊息排行榜)等資訊,適合使用Redis中的SortedSet結構進行儲存。


程式碼實現:

常見問題:

1.快取穿透和快取雪崩是什麼概念?

什麼是快取穿透?
一般的快取系統,都是按照key去快取查詢,如果不存在對應的value,就應該去後端系統查詢(比如DB)。如果key對應的value是一定不存在的,並且對該key併發請求量很大,就會對後端系統造成很大的壓力。這就叫做快取穿透

如何避免?
1:對查詢結果為空的情況也進行快取,快取時間設定短一點,或者該key對應的資料insert了之後清理快取。
2:對一定不存在的key進行過濾。可以把所有的可能存在的key放到一個大的Bitmap中,查詢時通過該bitmap過濾。【感覺應該用的不多吧】


快取雪崩
什麼是快取雪崩?
當快取伺服器重啟或者大量快取集中在某一個時間段失效,這樣在失效的時候,也會給後端系統(比如DB)帶來很大壓力。
如何避免?
1:在快取失效後,通過加鎖或者佇列來控制讀資料庫寫快取的執行緒數量。比如對某個key只允許一個執行緒查詢資料和寫快取,其他執行緒等待。
2:不同的key,設定不同的過期時間,讓快取失效的時間點儘量均勻。
3:做二級快取,A1為原始快取,A2為拷貝快取,A1失效時,可以訪問A2,A1快取失效時間設定為短期,A2設定為長期(此點為補充)

2.MySQL裡有2000w資料,Redis中只存20w的資料,如何保證Redis中的資料都是熱點資料(redis有哪些資料淘汰策略???)

redis 記憶體資料集大小上升到一定大小的時候,就會施行資料淘汰策略(回收策略)。redis 提供 6種資料淘汰策略:

  1. volatile-lru:從已設定過期時間的資料集(server.db[i].expires)中挑選最近最少使用的資料淘汰
  1. volatile-ttl:從已設定過期時間的資料集(server.db[i].expires)中挑選將要過期的資料淘汰
  1. volatile-random:從已設定過期時間的資料集(server.db[i].expires)中任意選擇資料淘汰
  1. allkeys-lru:從資料集(server.db[i].dict)中挑選最近最少使用的資料淘汰
  1. allkeys-random:從資料集(server.db[i].dict)中任意選擇資料淘汰
  1. no-enviction(驅逐):禁止驅逐資料
使用策略規則:
 1、如果資料呈現冪律分佈,也就是一部分資料訪問頻率高,一部分資料訪問頻率低,則使用allkeys-lru
 2、如果資料呈現平等分佈,也就是所有的資料訪問頻率都相同,則使用allkeys-random

3.redis的資料持久化的方式

1.RDB方式持久化

RDB方式是通過快照方式完成的,當符合一定條件時Redis會自動將記憶體中的所有資料進行快照並且儲存到硬碟上。進行快照的條件在配置檔案中指定,有2個引數構成:時間和改動鍵的個數,當在指定時間內被更改的鍵的個數大於指定數值時就會進行快照。RDB是Redis預設的持久化方式

在配置檔案中已經預置了三個條件

#save 900 1 # 15分鐘內至少有一個鍵被更改

#save 300 10 # 5分鐘內至少有10個鍵被更改

#save 60 10000 # 1分鐘內至少有10000個鍵被更改

2. AOF方式持久化

Redis的AOF持久化策略是將傳送到Redis服務端的每一條命令都記錄下來,並且儲存在硬碟的AOF檔案中。可以通過引數appendonly來設定是否啟用AOF。AOF檔案的位置和RDB的位置相同,都是通過dir引數設定,預設的檔名是appendonly.aof,可以通過appendfilename引數修改。