Redis資料結構

2022-02-14 22:50:02 字數 3512 閱讀 3922

首先在 redis 內部會使用乙個redisobject物件來表示所有的keyvalue。

redis是典型的key-value型別資料庫,key為字元型別,value的型別常用的為五種型別:string、hash 、list 、 set 、 sortedset。value還支援的高階型別:hyperloglog、布隆過濾器、geohash、bitm ap、pub/sub、stream

可以是string,也可是是任意的byte型別的陣列,如等。string 在 redis 內部儲存預設就是乙個字串,被 redisobject 所引用,當遇到 incr,decr 等操作時會轉成數值型進行計算,此時 redisobject 的 encoding 欄位為int。

最大為512mb,基本可以儲存任意啦。常用命令的時間複雜度為o(1),讀寫一樣的快。常用命令:get、set、incr、decr、mget等,參照redis常用命令中文版是最常用的一種資料型別,普通的key/ value 儲存都可以歸為此類,即可以完全實現目前 memcached 的功能,並且效率更高。還可以享受redis的定時持久化,操作日誌及 replication等功能。除了提供與 memcached 一樣的get、set、incr、decr 等操作外,redis還提供了下面一些操作: 

常規key-value快取應用。常規計數: 微博數, 粉絲數。

redis 的 hash 實際是內部儲存的 value 為乙個 hashmap,並提供了直接訪問這個 map 成員的介面。hash將物件的各個屬性存入map裡,可以只讀取/更新物件的某些屬性。另外不同的模組可以只更新自己關心的屬性而不會互相併發覆蓋衝突。

不同程式通過 key(使用者 id) + field(屬性標籤)就可以併發操作各自關心的屬性資料

redis hash 對應 value 內部實際就是乙個 hashmap,實際這裡會有2種不同實現, hash 的成員比較少時 redis 為了節省記憶體會採用類似一維陣列的方式來緊湊儲存,而不會採用真正的 hashmap 結構,對應的 value redisobject 的 encoding 為 zipmap,當成員數量增大時會自動轉成真正的 hashmap,此時 encoding 為 ht**。一般操作複雜度是o(1),要同時操作多個field時就是o(n),n是field的數量。

儲存部分變更資料,如使用者資訊等。

redis list 的應用場景非常多,也是 redis 最重要的資料結構之一,比如 twitter 的關注列表,粉絲列表等都可以用 redis 的 list 結構來實現,還提供了生產者消費者阻塞模式(b開頭的命令),常用於任務佇列,訊息佇列等

redis list 的實現為乙個雙向鍊錶,即可以支援反向查詢和遍歷,更方便操作,不過帶來了部分額外的記憶體開銷,redis 內部的很多實現,包括傳送緩衝佇列等也都是用的這個資料結構。  

如果消費者把job給pop走了又沒處理完就宕機了怎麼辦?

加多乙個sorted set,分發的時候同時發到list與sorted set,以分發時間為score,使用者把job做完了之後要用zrem消掉sorted set裡的job,並且定時從sorted set中取出超時沒有完成的任務,重新放回list。 如果發生重複可以在sorted set中在查詢確認一遍,或者將訊息的消費介面設計成冪等性。

為每個worker多加乙個的list,彈出任務時改用rpoplpush,將job同時放到worker自己的list中,完成時用lrem消掉。如果集群管理(如zookeeper)發現worker已經掛掉,就將worker的list內容重新放回主list

set就是hashset,可以將重複的元素隨便放入而set會自動去重,底層實現也是hashmap,並且 set 提供了判斷某個成員是否在乙個 set 集合內的重要介面,這個也是 list 所不能提供的。

set 的內部實現是乙個 value 永遠為 null 的 hashmap,實際就是通過計算 hash 的方式來快速排重的,這也是 set 能提供判斷乙個成員是否在集合內的原因。

set 不是自動有序的,而** sorted set 可以通過使用者額外提供乙個優先順序(score)的引數來為成員排序並且是插入有序的,即自動排序**。當你需要乙個有序的並且不重複的集合列表,那麼可以選擇 sorted set 資料結構,比如 twitter 的 publictimeline 可以以發表時間作為 score 來儲存,這樣獲取時就是自動按時間排好序的

內部使用 hashmap 和跳躍表(skiplist)來保證資料的儲存和有序

sorted set的實現是hashmap(element->score, 用於實現zscore及判斷element是否在集合內),和skiplist(score->element,按score排序)的混合體。skiplist有點像平衡二叉樹那樣,不同範圍的score被分成一層一層,每層是乙個按score排序的鍊錶。    

zadd/zrem是o(log(n));zrangebyscore/zremrangebyscore是o(log(n)+m),n是set大小,m是結果/操作元素的個數。複雜度的log取對數很關鍵,可以使,1000萬大小的set,複雜度也只是幾十不到。但是,如果一次命中很多元素m很大則複雜度很高。

上面的一些實現上的分析可以看出 redis 實際上的記憶體管理成本非常高,即占用了過多的記憶體,屬於用空間換時間。作者對這點也非常清楚,所以提供了一系列的引數和手段來控制和節省記憶體

vm 選項是作為 redis 儲存超出物理記憶體資料的一種資料在記憶體與磁碟換入換出的乙個持久化策略,將嚴重地拖垮系統的執行速度,所以要關閉 vm 功能,請檢查你的 redis.conf 檔案中 vm-enabled 為 no。

最好設定下 redis.conf 中的 maxmemory 選項,該選項是告訴 redis 當使用了多少物理記憶體後就開始拒絕後續的寫入請求,該引數能很好的保護好你的 redis 不會因為使用了過多的物理記憶體而導致 swap,最終嚴重影響效能甚至崩潰。

Redis資料結構

字典 dict 是redis裡最核心的資料結構,正如其全稱remote dictionary service所說,redis其實就是乙個字典服務,字典以key value的形式呈現給使用者,key是簡單的字串,而value可以是各種資料結構,比如字串 string 鍊錶 list 集合 set 排序...

Redis 資料結構

最近接觸到了redis的使用,借這個機會深入的了解一下redis的實現和設計原理。下面先介紹一下redis底層所用到的資料結構。redis的實現幾乎都是基於下面的幾個資料結構之上的。struct sdshdr struct listnode struct list struct dictentry ...

redis 資料結構

今天學習了redis的列表型別 lpush ltrim lrange lpush mylist content ltrim 0,99 lrange 0,1 lrange 兩個引數 分別代表第乙個元素和最後乙個元素 redis的列表型別,可以用來做訊息佇列 使用乙個程序 用lpush命名作為生產者 使...