日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

承接上文深入redis源碼,了解數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)思想

本地調(diào)試redis源碼

啟動(dòng)redis源碼

mac下載C語(yǔ)言編譯器CLion,拉取redis源碼并導(dǎo)入CLion

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

編譯redis源碼并啟動(dòng)

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

編譯成功之后,在src目錄中就會(huì)出現(xiàn)可執(zhí)行文件

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

啟動(dòng)redis-server

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

啟動(dòng)成功

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

在set方法中打個(gè)斷點(diǎn)

redis的所有命令都在redisCommand里面定義,找到set命令,并找到對(duì)應(yīng)的觸點(diǎn)函數(shù)setCommand

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

在setCommand函數(shù)中打個(gè)端點(diǎn)

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

通過(guò)redis-cli執(zhí)行set命令,就可以斷點(diǎn)跟蹤了

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

看下編碼的過(guò)程

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

tryObjectEncoding

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

len是value的長(zhǎng)度,長(zhǎng)度小于等于20的話,才可以被轉(zhuǎn)換成整數(shù)。

為什么整數(shù)范圍最大是十進(jìn)制數(shù)20?

在64位系統(tǒng)下C語(yǔ)言中的int還是占4字節(jié),32位,與32位系統(tǒng)中沒(méi)有區(qū)別!

64位操作系統(tǒng)下,采用64位編譯器進(jìn)行編譯處理時(shí),發(fā)生變化的變量類型是long。

32位系統(tǒng)下,long占4字節(jié),32位,與int相同。

64位系統(tǒng)下,long占8字節(jié),64位,有符號(hào)數(shù)取值范圍是-9223372036854775808至9223372036854775807。

JAVA的long型整數(shù)最大值:9223372036854775807,即19位十進(jìn)制數(shù),64位二進(jìn)制數(shù),16位16進(jìn)制數(shù)。

long占8個(gè)字節(jié),64位二進(jìn)制數(shù),19位十進(jìn)制數(shù),算上符號(hào)的話就是20位十進(jìn)制數(shù)。

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

如果value string可以轉(zhuǎn)換成long,然后將value值賦值給redisObject的ptr指針,強(qiáng)制把整型值轉(zhuǎn)換成指針類型,而不讓ptr存內(nèi)存地址,這樣即節(jié)省了內(nèi)存,還減少了一次內(nèi)存io。

字符串編碼

短字符串編碼

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

短字符串(長(zhǎng)度小于等于44)編碼是embstr

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

長(zhǎng)字符串(長(zhǎng)度大于44)編碼是raw

為什么是44?

要充分理解這個(gè)問(wèn)題,需要先科普下cpu、地址總線、內(nèi)存之間的關(guān)系:

  • • 64位處理器比32位處理器速度更快

32位處理器一次性只能處理32位,也就是4個(gè)字節(jié)的數(shù)據(jù),而64位處理器一次性能處理64位即8個(gè)字節(jié)的數(shù)據(jù),64位處理器的處理速度比32位更快。

  • • 64位處理器比32位能處理的地址范圍更大

除了運(yùn)算能力之外,與32位處理器相比,64位處理器的優(yōu)勢(shì)還體現(xiàn)在系統(tǒng)對(duì)內(nèi)存的控制上。由于地址使用的是特殊的整數(shù),而64位處理器的一個(gè)ALU(算術(shù)邏輯運(yùn)行器)和寄存器可以處理更大的整數(shù),也就是更大的地址。傳統(tǒng)的32位處理器的尋址空間最大為4GB,而64位處理器在理論上則可以達(dá)到1800萬(wàn)個(gè)TB。

  • • 地址總線

要存取數(shù)據(jù)或指令就要知道數(shù)據(jù)或指令存放的位置,地址寄存器存儲(chǔ)的就是cpu當(dāng)前要存取的數(shù)據(jù)或指令的地址,該地址是由地址總線傳輸?shù)降刂芳拇嫫魃系?/p>

假設(shè)地址總線有n位,即共有n位二進(jìn)制位來(lái)表示地址,那么最多可以表示2^n個(gè)地址,另外計(jì)算機(jī)以一個(gè)字節(jié)為尋址單位,所以cpu的尋址能力或者最大的尋址范圍是2^n個(gè)字節(jié)。綜上,地址總線的位數(shù)決定了cpu的尋址能力。

  • • 數(shù)據(jù)總線的寬度與字長(zhǎng)及cpu位數(shù)

字長(zhǎng)指cpu同一時(shí)間內(nèi)可以處理的二進(jìn)制數(shù)的位數(shù),數(shù)據(jù)總線傳輸?shù)臄?shù)據(jù)或指令的位數(shù)要與字長(zhǎng)一致。否則,如果數(shù)據(jù)總線長(zhǎng)度大于字長(zhǎng)則一條數(shù)據(jù)或指令要分多次傳輸,則分開(kāi)傳輸幾組數(shù)據(jù)也就沒(méi)有意義;如果數(shù)據(jù)總線寬度小于字長(zhǎng),則cpu的利用率降低,對(duì)資源是種浪費(fèi)。另外如果字長(zhǎng)是n位,一般稱cpu是n位的,所以說(shuō)數(shù)據(jù)總線的寬度和字長(zhǎng)及cpu的位數(shù)是一致的。

結(jié)合上面的問(wèn)題,繼續(xù)分析:

64位系統(tǒng)緩存行(字長(zhǎng))大小是64字節(jié)即64位處理器一次性讀取64字節(jié)的緩存數(shù)據(jù)。基于緩存局部性原理,一次性要讀取的數(shù)據(jù)不足64字節(jié),也會(huì)順便獲取相鄰的其他數(shù)據(jù)共64字節(jié)。

從內(nèi)存中獲取到redisObject對(duì)象之后,根據(jù)ptr指向的內(nèi)存空間獲取數(shù)據(jù)。

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

分析下這個(gè)redisObject對(duì)象占多少個(gè)字節(jié):

type 4bit,encoding4bit,LRU_BITS占24bit即3字節(jié),int類型的refcount占4字節(jié),ptr指針類型占8字節(jié),共16個(gè)字節(jié),那么64字節(jié)的緩存行還剩48個(gè)字節(jié)的剩余空間,那么這48字節(jié)的緩存行空間存放什么呢?

存放redisObject ptr指針指向的內(nèi)存空間的數(shù)據(jù),即cpu一次性讀取的64字節(jié)的緩存行中包含redisObject對(duì)象以及該對(duì)象ptr指針?biāo)赶虻膬?nèi)存空間的數(shù)據(jù),以免再根據(jù)redisObject的ptr指針再去內(nèi)存中獲取對(duì)應(yīng)的數(shù)據(jù),減少了一次內(nèi)存io。

那48字節(jié)在哪個(gè)字符串類型的范圍內(nèi)呢?

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

sdshdr8 對(duì)應(yīng)的字符串范圍是32-64字節(jié)

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

c語(yǔ)言中的char類型占1個(gè)字節(jié),java中的char類型占2個(gè)字節(jié)。

redis字符串為了兼容c語(yǔ)言函數(shù)庫(kù)在末尾加上的字符占1個(gè)字節(jié)。

uint8_t len 占一個(gè)字節(jié),uint8_t alloc占一個(gè)字節(jié),char flags占一個(gè)字節(jié),占一個(gè)字節(jié)

所以sdshdr8數(shù)據(jù)結(jié)構(gòu)需要4個(gè)字節(jié)的元數(shù)據(jù)

除去這4個(gè)字節(jié),緩存行還有48-4=44個(gè)字節(jié)的剩余空間,如果字符串?dāng)?shù)據(jù)范圍小于等于44,把redisObject對(duì)象ptr指針?biāo)赶騼?nèi)存中的這個(gè)數(shù)據(jù)和redisObject對(duì)象放在一起即嵌入式字符串,在內(nèi)存空間分配的時(shí)候,這兩部分?jǐn)?shù)據(jù)是分配在一起的,這樣就可以直接適應(yīng)緩存行的大小,這樣就減少了一次內(nèi)存io。

List數(shù)據(jù)類型

  • • LPUSH
Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

從左邊開(kāi)始往alist中放入元素

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

  • • LPOP

從左邊獲取元素

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

依次是c、b、a

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

list如果沒(méi)有元素的話,對(duì)應(yīng)的key也會(huì)被清除

  • • RPUSH
Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

從右邊放入元素

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

從左邊放入元素,從左邊拿出元素,則是棧的數(shù)據(jù)結(jié)構(gòu)即a,b,c的數(shù)據(jù)放入,c、b、a順序的拿出,a最開(kāi)始進(jìn),最后出,先進(jìn)后出,

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

同一端,從這邊進(jìn),也從這邊出,這就是棧的數(shù)據(jù)結(jié)構(gòu)。

一邊進(jìn),另外一邊出,是隊(duì)列的數(shù)據(jù)結(jié)構(gòu)即右邊放a,b,c,左邊拿a,b,c,這是隊(duì)列的數(shù)據(jù)結(jié)構(gòu)。

阻塞api

如果沒(méi)有元素就一直等待,直到有元素或者設(shè)置超時(shí)時(shí)間

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

LPOP從list中彈出元素之后就會(huì)從list中刪除,如果應(yīng)用程序沒(méi)有正確處理的話,就會(huì)造成元素丟失的情況,BRPOPLPUSH就是為了應(yīng)對(duì)這場(chǎng)場(chǎng)景,彈出元素之后,push到另外一個(gè)list中,做一個(gè)數(shù)據(jù)備份,防止數(shù)據(jù)丟失。

List數(shù)據(jù)類型底層設(shè)計(jì)

List是一個(gè)有序(按加入的時(shí)序排序)的數(shù)據(jù)結(jié)構(gòu),Redis采用quicklist(雙端鏈表)和ziplist作為L(zhǎng)ist的底層實(shí)現(xiàn)。

可以通過(guò)設(shè)置每個(gè)ziplist的最大容量,quicklist的數(shù)據(jù)壓縮范圍,提升數(shù)據(jù)存取效率。

  • • list-max-ziplist-size -2

單個(gè)ziplist節(jié)點(diǎn)最大能存儲(chǔ)8kb,超過(guò)則進(jìn)行分裂,將數(shù)據(jù)存儲(chǔ)在新的ziplist節(jié)點(diǎn)中

  • • list-compress-depth 1

0代表所有節(jié)點(diǎn),都不進(jìn)行壓縮,1代表從頭節(jié)點(diǎn)往后走一個(gè),尾節(jié)點(diǎn)往前走一個(gè)不用壓縮,其他的全部壓縮,2,3,4...依次類推

Redis底層字符串編碼設(shè)計(jì)思想簡(jiǎn)介

 

雙端鏈表需要兩個(gè)指針:pre,next,而指針占8個(gè)字節(jié)的內(nèi)存空間,所以存儲(chǔ)一個(gè)元素就至少占16個(gè)字節(jié),如果元素比較多的情況下,內(nèi)存開(kāi)銷就會(huì)非常大,所以redis并沒(méi)有用quicklist 雙端鏈表,而是用更加緊湊的ziplist。

分享到:
標(biāo)簽:Redis
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定