Redis入門(一):Redis 簡介

Redis 是什麼?

Redis是一個開源(BSD許可)的,利用內存進行存儲的數據結構存儲系統;它可以用作數據庫、緩存和消息中間件。

  • redis由意大利人 Salvatore Sanfilippo 使用C語言開發
  • redis支持字符串(string)、列表(list)、集合(set)、有序集合(zset)、散列表(hash)五種基本數據結構類型
  • redis從 2.2.0 版本開始支持bitmap;在 2.8.9 版本添加了 HyperLogLog 用以進行基數統計;在 3.2 版本中新增了對GEO(地理位置)的支持
  • redis支持簡單事物與數據持久化,提供 RDB、AOF兩種可選的持久化方式
  • redis可以用作數據庫、緩存、消息隊列等

Redis 數據結構

value 對應的五種數據結構

Redis存儲key-value鍵值對數據,其中key類型為字符串,value對應五種數據結構,如下圖所示:

Redis入門(一):Redis 簡介

value 對應的五種數據結構

  • 字符串(string)類型的數據結構,對應的就是一個普通的字符串
  • 散列表(hash)類型的數據結構,對應的就是一個hash table,散列表特別適合用於存儲對象
  • 列表(list)類型的數據結構,對應的就是一個雙向列表,按照插入順序排序
  • 集合(set)類型的數據結構,對應的就是一個string類型的無序集合,集合中的數據不能重複出現
  • 有序集合(zset)類型的數據結構, 對應的就是一個string類型的有序集合,排序因子為每個元素附帶的一個double型的分數

Redis 核心對象 redisObject

在redis的 key-value存儲系統中,value 類型則為 redis 對象 redisObject, redisObject對象可以綁定對應的五種數據類型,如下圖所示:

Redis入門(一):Redis 簡介

Redis 核心對象 redisObject

  • 數據類型(type),對應五種數據類型
  • 編碼方式(encoding),指定所綁定數據類型的編碼方式
  • 數據指針(ptr), 指向對象底層實現的數據結構
  • 虛擬內存(vm), 該功能默認處於關閉狀態,只有打開了redis的虛擬內存功能,才會給vm分配真正的內存

編碼方式(encoding)

  • raw RAW編碼方式使用簡單動態字符串來保存字符串對象,才有預分配空間的方式來避免字符串修改時頻繁的分配釋放內存
  • int INT編碼方式以整數保存字符串數據,僅限能用long類型值表達的字符串
  • embstr 從Redis 3.0版本開始字符串引入了EMBSTR編碼方式,長度小於OBJ_ENCODING_EMBSTR_SIZE_LIMIT(39)的字符串將以EMBSTR方式存儲。採用這個方式可以減少內存分配的次數,提高內存分配的效率,降低內存碎片率。
  • hashtable 當數據類型無法滿足使用ziplist的條件時,Redis會使用hashtable作為數據結構的內部實現
  • ziplist 列表(List),散列表(Hash),有序集合(Sorted Set)在成員較少,成員值較小的時候都會採用壓縮列表(ZIPLIST)編碼方式進行存儲;成員值”較小”的標準可以通過配置項進行配置;壓縮列表簡單來說就是一系列連續的內存數據塊,其內存利用率很高,但增刪改查效率較低,所以只會在成員較少,值較小的情況下使用。
  • linkedlist 在Redis 3.2版本之前,一般的鏈表使用LINKDEDLIST編碼。在Redis 3.2版本開始,所有的鏈表都是用QUICKLIST編碼。兩者都是使用基本的雙端鏈表數據結構,區別是QUICKLIST每個節點的值都是使用ZIPLIST進行存儲的。
  • skiplist 跳躍表(SKIPLIST)編碼方式為有序集合對象專用,有序集合對象採用了字典+跳躍表的方式實現;其中字典裡面保存了有序集合中member與score的鍵值對,跳躍表則用於實現按score排序的功能
  • intset 當一個集合只包含整數值元素, 並且這個集合的元素數量不多時, Redis 就會使用整數集合作為集合鍵的底層實現

Redis這種通過redisObject指定數據結構編碼方式的設計有兩個好處:

  • 可以改進內部編碼,而對外的數據結構和命令沒有影響,這樣一旦開發開發出優秀的內部編碼,無需改動外部數據結構和命令。
  • 多種內部編碼實現可以在不同場景下發揮各自的優勢。例如ziplist比較節省內存,但是在列表元素比較多的情況下,性能會有所下降,這時候Redis會根據配置選項將列表類型的內部實現轉換為linkedlist。

Redis 五種數據結構對應的內部編碼

Redis在不同的情況下會為數據對象選擇適合的編碼方式

Redis入門(一):Redis 簡介

Redis 五種數據結構對應的內部編碼

string

  • int:8個字節的長整型
  • embstr:小於等於39個字節的字符串
  • raw:大於39個字節的字符串

hash

  • ziplist(壓縮列表):當哈希類型元素個數小於hash-max-ziplist-entries配置(默認512個),同時所有值都小於hash-max-ziplist-value配置(默認64個字節)時,Redis會使用ziplist作為哈希的內部實現ziplist使用更加緊湊的結構實現多個元素的連續存儲,所以在節省內存方面比hashtable更加優秀
  • hashtable(哈希表):當哈希類型無法滿足ziplist的條件時,Redis會使用hashtable作為哈希的內部實現。因為此時ziplist的讀寫效率會下降,而hashtable的讀寫時間複雜度為O(1)

list

  • ziplist(壓縮列表):當哈希類型元素個數小於hash-max-ziplist-entries配置(默認512個)同時所有值都小於hash-max-ziplist-value配置(默認64個字節)時,Redis會使用ziplist作為哈希的內部實現
  • linkedlist(鏈表):當列表類型無法滿足ziplist的條件時,Redis會使用linkedlist作為列表的內部實現

set

  • intset(整數集合):當集合中的元素都是整數且元素個數小於set-max-intset-entries配置(默認512個)時,Redis會選用intset來作為集合內部實現,從而減少內存的使用。
  • hashtable(哈希表):當集合類型無法滿足intset的條件時,Redis會使用hashtable作為集合的內部實現

zset

  • ziplist(壓縮列表):當有序集合的元素個數小於zset-max-ziplist-entries配置(默認128個)同時每個元素的值小於zset-max-ziplist-value配置(默認64個字節)時,Redis會用ziplist來作為有序集合的內部實現,ziplist可以有效減少內存使用
  • skiplist(跳躍表):當ziplist條件不滿足時,有序集合會使用skiplist作為內部實現,因為此時zip的讀寫效率會下降

reference

  • redis中文官網
  • 菜鳥教程-Redis
  • Redis數據編碼方式詳解
  • Redis的五種數據結構的內部編碼


分享到:


相關文章: