日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

《Redis 设计与实现》读书笔记-Redis 对象

發布時間:2024/9/30 数据库 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Redis 设计与实现》读书笔记-Redis 对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、Redis 對象

1.1 Redis 對象簡介

Redis 使用對象來表示數據庫中鍵和值,當我們在數據庫中存儲一個鍵值對時,至少會創建兩個對象,一個對象用于存儲鍵值對的鍵,另一個對象用于存儲鍵值對的值。

Redis 中的每一個對象都由一個 redisObject 結構表示,該結構有三個屬性和保存的數據有關,分別是 type 屬性、encoding 屬性和 ptr 屬性。

typedef struct redisObject {// 類型unsigned type:4;// 編碼unsigned encoding:4;// 指向底層數據實現數據結構的指針void *ptr; } robj;

1.2 對象類型

redisObject 對象的 type 屬性記錄了對象的類型,Redis 中的鍵總是一個字符串對象,值對象可以是字符串對象、哈希對象、集合對象等。

我們可以通過使用 TYPE key 命令查看數據庫鍵對應的值對象的類型。

1.3 編碼與底層實現

encoding 屬性記錄了對象所使用的編碼,也就是這個對象底層實現的數據結構。關于編碼可以使用 OBJECT ENCODING key 命令查看。

二、五種數據類型對象與編碼

2.1 字符串對象

要注意的是 long、double 浮點數在 Redis 中也是作為字符串值來保存的。

(1)字符串對象編碼

字符串對象的編碼有 int 、 raw 或者 embstr 三種。

  • int:保存的是整數值
  • raw:保存的是字符串,并且字符串的長度小于等于 39 個字節
  • embstr:保存的是字符串,并且字符串的長度大于等于 39 個字節

embstr 編碼的好處:

  • embstr 編碼將創建字符串對象所需的內存分配次數從 raw 編碼的兩次降低為一次。
  • 釋放 embstr 編碼的字符串對象只需要調用一次內存釋放函數, 而釋放 raw 編碼的字符串對象需要調用兩次內存釋放函數。
  • 因為 embstr 編碼的字符串對象的所有數據都保存在一塊連續的內存里面,所以這種編碼的字符串對象比起 raw 編碼的字符串對象能夠更好地利用緩存帶來的優勢。

(2)編碼轉換

int 編碼的字符串對象和 embstr 編碼的字符串對象在一定條件下, 會被轉換為 raw 編碼的字符串對象,如下。

  • int 編碼的字符串對象通過某些操作,保存的不再是單純的整數值
  • 對 embstr 編碼的字符串對象執行任何修改命令時, 程序會先將對象的編碼從 embstr 轉換成 raw , 然后再執行修改命令

下面是一個例子,供參考:

127.0.0.1:6379> SET num-str 100 OK 127.0.0.1:6379> OBJECT ENCODING num-str "int" # 追加元素內容 127.0.0.1:6379> APPEND num-str "hei~" (integer) 7 127.0.0.1:6379> OBJECT ENCODING num-str "raw"

2.2 列表對象

(1)列表對象編碼

Redis 3.2 以前的版本中列表的的編碼類型有 ziplist 或 linkedlist。

ziplist 編碼的列表對象使用壓縮列表作為底層實現, 每個壓縮列表節點(entry)保存了一個列表元素。

linkedlist 編碼的列表對象使用雙端鏈表作為底層實現, 每個雙端鏈表節點(node)都保存了一個字符串對象, 而每個字符串對象都保存了一個列表元素。

在 Redis 3.2 以上的版本中列表對象的編碼替換為 quicklist,它的底層實現是一個雙向鏈表,而且是一個ziplist 數據結構的雙向鏈表。關于這種數據結構的詳細信息就不介紹了,以后有機會接觸到 Redis 的源碼后再單獨拿出來總結。

例子如下(基于 3.2.× 版本):

127.0.0.1:6379> RPUSH students "zs" "ls" "ww" (integer) 3 127.0.0.1:6379> OBJECT ENCODING students "quicklist"

2.3 哈希對象

(1)哈希對象編碼

哈希對象的編碼是 ziplist 或 hashtable。

ziplist 編碼的哈希對象使用壓縮列表作為底層實現,每當有新的鍵值對要加入到哈希對象時,程序會先將保存了鍵的壓縮列表節點推入到壓縮列表表尾,然后再將保存了值的壓縮列表節點推入到壓縮列表表尾。因此保存了同一鍵值對的兩個節點總是緊挨在一起, 保存鍵的節點在前, 保存值的節點在后。

hashtable 編碼的哈希對象使用字典作為底層實現,哈希對象中的每個鍵值對都使用一個字典鍵值對來保存。

(2)編碼轉換

當哈希對象可以同時滿足以下兩個條件時, 哈希對象使用 ziplist 編碼。

  • 鍵和值的字符串長度都小于 64 字節
  • 鍵值對數量小于 512 個

不能滿足上面兩個條件的哈希對象使用 hashtable 編碼。

PS:
上面兩個條件的上限值是可以在配置文件中修改的,默認配置如下:

hash-max-ziplist-entries 512 hash-max-ziplist-value 64

下面是一個例子:

127.0.0.1:6379> OBJECT ENCODING student "ziplist" # 存儲一個大于 64 字節的值 127.0.0.1:6379> HSET student desc "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz ... " (integer) 1 127.0.0.1:6379> OBJECT ENCODING student "hashtable"

2.4 集合對象

(1)集合對象編碼

集合對象的編碼可以是 intset 或者 hashtable 。

inset 編碼的底層實現是整數集合,集合對象包含的所有元素都被保存在整數集合里。

hashtable 編碼使用字典作為底層實現,字典的每個鍵都是一個字符串對象,每個字符串對象包含了一個集合元素,而字典的值則全部被設置為 NULL ,可以類比于 Java 中的 HashSet 的實現。

(2)編碼轉換

當集合對象可以滿足以下兩個條件中的任一個時, 對象使用 intset 編碼:

  • 集合對象中的元素都是整數值
  • 集合對象中元素的數量不超過 512 個

PS:
上面第二個條件的上限值是可以在配置文件中修改的,默認配置如下:

set-max-intset-entries 512

下面是一個例子:

127.0.0.1:6379> SADD keys "1" "2" (integer) 2 127.0.0.1:6379> OBJECT ENCODING keys "intset" # 添加非整數元素 127.0.0.1:6379> SADD keys "hei~" (integer) 1 127.0.0.1:6379> OBJECT ENCODING keys "hashtable"

2.5有序集合對象

(1)有序集合對象編碼

有序集合的編碼可以是 ziplist 或者 skiplist 。

壓縮列表內的集合元素按分值從小到大進行排序,分值較小的元素被放置在靠近表頭的方向, 分值較大的元素則被放置在靠近表尾的方向。

skiplist 編碼的有序集合對象使用 zset 結構作為底層實現, 一個 zset 結構同時包含一個字典和一個跳躍表。

為什么 zset 結構要同時使用字典與跳躍表來實現有序集合?

  • 如果只使用字典實現有序集合,查找成員的復雜度為O(1),但是當執行范圍操作時,就需要對字典中保存的元素進行排序。
  • 如果只使用跳躍表實現有序集合,執行范圍操作時的所有優點都會被保留,但是執行查找元素時,時間復雜度上升為O(logN)
  • 因此 zset 集成了字典與跳躍表兩者的優點來實現有序集合對象。

(2)有序集合對象編碼轉換

當有序集合對象滿足以下條件時,對象會使用 ziplist 編碼:

  • 有序集合保存的元素數量小雨 128 個
  • 有序集合保存的所有元素成員長度小于 64 字節

PS:
上面第二個條件的上限值是可以在配置文件中修改的,默認配置如下:

zset-max-ziplist-entries 128 zset-max-ziplist-value 64

三、Other

3.1內存回收

C 語言自身不具備內存回收功能,因此 Redis 使用引用計數(refering counting)實現內存回收機制。每個對象的引用計數信息由 redisO此處輸入代碼bject 結構中的 refcount 屬性記錄。

在對象創建時,引用計數值會被初始化為 1,當對象被程序引用時,引用計數值會加 1,當對象不在被一個對象使用時,它的引用計數值會減 1,當對象的引用計數值為 0 時,對象所占的內存就會被回收。

3.2對象共享

Redis 會在初始化服務器時,創建 [0 ,10000) 之間的字符串對象,當服務器需要用到 0 到 9999 之間的字符串對象時,服務器會共享這些對象,而不是創建新的對象,通過這種方式可以節約內存。

參考書籍

《Redis 設計與實現》黃健宏著

總結

以上是生活随笔為你收集整理的《Redis 设计与实现》读书笔记-Redis 对象的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。