欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

redis數(shù)據(jù)結(jié)構(gòu)之String詳解

 更新時間:2025年08月15日 08:51:47   作者:ruan114514  
Redis以String為基礎(chǔ)類型,因C字符串效率低、非二進制安全等問題,采用SDS動態(tài)字符串實現(xiàn)高效存儲,通過RedisObject封裝,支持多種編碼方式(如RAW、EMBSTR、INT)和內(nèi)存優(yōu)化策略,靈活管理數(shù)據(jù)結(jié)構(gòu)與內(nèi)存使用

一、為什么Redis選String作為基礎(chǔ)類型?

redis中的所有key是字符串,所有value本質(zhì)上也是字符串,比如 集合set中的每一個 成員 都是一個獨立的字符串對象,列表中的每一個 元素 都是一個獨立的字符串對象,整個HASH是一個對象,它內(nèi)部的每一個 字段(field) 和一個字段值(value) 都是一個獨立的字符串對象

redis是通過c語言來實現(xiàn)的,但是沒有直接使用c語言中的字符串,有幾下幾點原因

  • 獲取字符串長度需要通過運算:C字符串以\0(空字符)結(jié)尾,要獲取長度必須遍歷整個數(shù)組直到遇到\0,時間復(fù)雜度為O(n),這在高性能數(shù)據(jù)庫如Redis中效率低下。
  • 非二進制安全:C字符串不能存儲任意二進制數(shù)據(jù),因為它依賴于\0作為結(jié)束符。如果數(shù)據(jù)中包含\0(如一些二進制文件),會被錯誤截斷,破壞數(shù)據(jù)完整性。
  • 不可修改:C語言字符串常量(如char* s = "hello")是只讀的,無法直接擴展或修改其長度,這在動態(tài)數(shù)據(jù)存儲中不靈活。

Redis的解決方案:Redis因此構(gòu)建了自己的字符串結(jié)構(gòu)——SDS(簡單動態(tài)字符串),它通過設(shè)計一個智能結(jié)構(gòu)來支持查找、二進制安全性和動態(tài)修改。

二、SDS底層數(shù)據(jù)結(jié)構(gòu)

uint8_t (8位無符號整數(shù)),可表示的最大值是 255 (因為 2^8 - 1 = 255),因此 len 最多記錄 255 字節(jié) 的長度,否則會溢出,如果一個 SDS 字符串的實際長度超過 255 字節(jié),Redis 會自動選擇更大容量的結(jié)構(gòu)體(如 sdshdr16/sdshdr32)。

三、RedisObject是什么

通常我們了解的數(shù)據(jù)結(jié)構(gòu)有字符串、雙端鏈表、字典、壓縮列表、整數(shù)集合等,但是Redis為了加快讀寫速度,并沒有直接使用這些數(shù)據(jù)結(jié)構(gòu),而是在此基礎(chǔ)上又包裝了一層稱之為RedisObject。

RedisObject 有五種對象:字符串對象(String)、列表對象(List)、哈希對象(Hash)、集合對象(Set)和有序集合對象(ZSet)。

1.type:數(shù)據(jù)類型標(biāo)識(4 bit)就是redis基本類型

類型常量對應(yīng)數(shù)據(jù)結(jié)構(gòu)
OBJ_STRING0字符串
OBJ_LIST1列表
OBJ_SET2集合
OBJ_ZSET3有序集合
OBJ_HASH4哈希表

2.encoding:內(nèi)部編碼(4 bit)

同一數(shù)據(jù)類型可對應(yīng)不同底層實現(xiàn):

編碼常量適用類型底層結(jié)構(gòu)
OBJ_ENCODING_INT0String整數(shù)存儲
OBJ_ENCODING_EMBSTR1String短字符串優(yōu)化
OBJ_ENCODING_RAW2StringSDS動態(tài)字符串
OBJ_ENCODING_HT3Hash/Set哈希表
OBJ_ENCODING_ZIPLIST4List/Hash/Zset壓縮列表
OBJ_ENCODING_QUICKLIST5List快速列表
OBJ_ENCODING_SKIPLIST6Zset跳表
OBJ_ENCODING_STREAM7Stream流數(shù)據(jù)結(jié)構(gòu)

動態(tài)編碼轉(zhuǎn)換示例:

  • 當(dāng) Hash 的元素超過 hash-max-ziplist-entries 時
  • OBJ_ENCODING_ZIPLIST → OBJ_ENCODING_HT

3.lru:緩存淘汰信息(24 bit)

  • LRU模式:記錄對象最后訪問時間戳(精度:秒級)
  • LFU模式(Redis 4.0+):
16 bits      8 bits
+------------+------+
| 訪問時間戳   | 頻率 |
+------------+------+
  • 頻率(logc):基于概率遞增的訪問計數(shù)器
  • 時間戳:解決冷數(shù)據(jù)滯留問題

4.refcount:引用計數(shù)(4字節(jié))

  • 內(nèi)存回收refcount=0 時自動釋放內(nèi)存
  • 對象共享:相同數(shù)據(jù)復(fù)用對象(如 SET key 100 共享整數(shù)對象)
  • 多客戶端引用:同一 key 被多個客戶端連接引用

5.ptr:數(shù)據(jù)指針(8字節(jié))

指向?qū)嶋H數(shù)據(jù)結(jié)構(gòu),如:

  • OBJ_ENCODING_INT → 直接存儲整數(shù)(void * 強轉(zhuǎn)為 long
  • OBJ_ENCODING_RAW → 指向 sds 結(jié)構(gòu)
  • OBJ_ENCODING_HT → 指向 dict 哈希表

四、String類型數(shù)據(jù)結(jié)構(gòu)

string類型在redis中有三種編碼方式

RAW編碼

分配兩次內(nèi)存 RedisObject和SDS的內(nèi)存不連續(xù) 兩個數(shù)據(jù)結(jié)構(gòu)申請了兩片內(nèi)存區(qū)域

EMBSTR編碼

INT編碼

為什么分界線是44字節(jié)?

44字節(jié)的臨界值源于內(nèi)存分配器的優(yōu)化策略,具體計算如下:

1. 內(nèi)存分配器的最小單位

  • Redis 默認(rèn)使用 jemalloc 或 glibc malloc
  • 這些分配器的最小分配單元通常是 64字節(jié)(CPU緩存行對齊)

2. EMBSTR 的總內(nèi)存占用公式

總大小 = RedisObject(16字節(jié)) + SDS頭部(3字節(jié)) + 字符串內(nèi)容(N字節(jié)) + 結(jié)束符\0(1字節(jié))
  • 最大允許占用:64字節(jié)(分配器最小單元)
  • 固定開銷:16(robj) + 3(sds) + 1(\0) = 20字節(jié)
  • 可用空間:64 - 20 = 44字節(jié)
編碼類型OBJ_ENCODING_INTOBJ_ENCODING_EMBSTROBJ_ENCODING_RAW
觸發(fā)條件數(shù)值類型且值在 [LONG_MIN, LONG_MAX]字符串長度 ≤ 44字節(jié)字符串長度 > 44字節(jié)
內(nèi)存分配次數(shù)1次(RedisObject內(nèi)聯(lián)存儲)1次(連續(xù)內(nèi)存塊)2次(RedisObject + SDS分開)
適用場景計數(shù)器(如 INCR 操作)短字符串(如JSON片段、短URL)長文本、二進制數(shù)據(jù)
修改時的行為直接替換整數(shù)值自動轉(zhuǎn)換為 RAW 編碼原地修改或重新分配
內(nèi)存占用示例存儲 100:16字節(jié)(RedisObject)存儲 "hello":16+6=22字節(jié)存儲1KB文本:16+1024+9=1049字節(jié)

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • redis和redission分布式鎖原理及區(qū)別說明

    redis和redission分布式鎖原理及區(qū)別說明

    文章對比了synchronized、樂觀鎖、Redis分布式鎖及Redission鎖的原理與區(qū)別,指出在集群環(huán)境下synchronized失效,樂觀鎖存在數(shù)據(jù)庫性能瓶頸,而Redission通過watchdog自動續(xù)期和Lua原子操作解決Redis鎖的超時問題,推薦其在高并發(fā)場景下的可靠性與易用性
    2025-08-08
  • Redis?Brpop?命令作用詳解

    Redis?Brpop?命令作用詳解

    BRPOP?是一個阻塞的列表彈出原語,該命令會按照給出的?key?順序查看?list,并在找到的第一個非空?list?的尾部彈出一個元素,今天通過本文給大家介紹Redis?Brpop?命令相關(guān)知識,感興趣的朋友一起看看吧
    2023-07-07
  • Mac中Redis服務(wù)啟動時錯誤信息:NOAUTH Authentication required

    Mac中Redis服務(wù)啟動時錯誤信息:NOAUTH Authentication required

    這篇文章主要介紹了Mac中使用Redis服務(wù)啟動時錯誤信息:"NOAUTH Authentication required"問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Redis報錯:無法連接Redis服務(wù)的解決方法

    Redis報錯:無法連接Redis服務(wù)的解決方法

    在Linux系統(tǒng)上運行Redis服務(wù)時,有時會遇到“無法連接Redis服務(wù)”的報錯,本文就詳細的介紹一下解決方法,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • 使用RedisAtomicInteger計數(shù)出現(xiàn)少計問題及解決

    使用RedisAtomicInteger計數(shù)出現(xiàn)少計問題及解決

    這篇文章主要介紹了使用RedisAtomicInteger計數(shù)出現(xiàn)少計問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • redis?zset實現(xiàn)滑動窗口限流的代碼

    redis?zset實現(xiàn)滑動窗口限流的代碼

    這篇文章主要介紹了redis?zset實現(xiàn)滑動窗口限流,滑動窗口算法思想就是記錄一個滑動的時間窗口內(nèi)的操作次數(shù),操作次數(shù)超過閾值則進行限流,本文通過實例代碼給大家詳細介紹,需要的朋友參考下吧
    2022-03-03
  • Redis中緩存穿透的實現(xiàn)示例

    Redis中緩存穿透的實現(xiàn)示例

    本文主要介紹了Redis中緩存穿透的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-07-07
  • Redis不同數(shù)據(jù)類型使用場景代碼實例

    Redis不同數(shù)據(jù)類型使用場景代碼實例

    這篇文章主要介紹了Redis不同數(shù)據(jù)類型使用場景代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-12-12
  • 使用Redis實現(xiàn)延時任務(wù)的解決方案

    使用Redis實現(xiàn)延時任務(wù)的解決方案

    這篇文章主要介紹了使用Redis實現(xiàn)延時任務(wù)的解決方案,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • Redis跳躍表的基本原理和實現(xiàn)

    Redis跳躍表的基本原理和實現(xiàn)

    本文主要介紹了Redis跳躍表的基本原理和實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06

最新評論