欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:Redis進(jìn)階知識個人匯總

柚子快報邀請碼778899分享:Redis進(jìn)階知識個人匯總

http://yzkb.51969.com/

持久化

三種方式實(shí)現(xiàn)它的持久化:

RDB持久化

全稱Redis數(shù)據(jù)備份文件,又稱Redis數(shù)據(jù)快照 這種就是將Redis內(nèi)存中所有數(shù)據(jù)記錄到磁盤中,當(dāng)實(shí)例出故障后,從磁盤中讀快照文件進(jìn)行恢復(fù)數(shù)據(jù)。 一般使用bgsave指令實(shí)現(xiàn)

復(fù)制主線程得到一個子進(jìn)程,共享同一內(nèi)存空間 子進(jìn)程讀取Redis內(nèi)存數(shù)據(jù),并寫入一個新RDB文件 最后,用新的RDB文件替代舊的 可以配置:save 60 100

代表60s內(nèi)至少執(zhí)行100次觸發(fā)RDB 缺點(diǎn)

RDB執(zhí)行間隔長,兩次RDB之間寫有數(shù)據(jù)丟失風(fēng)險 fork子進(jìn)程、壓縮、寫RDB文件都耗時 AOF持久化

全稱追加文件 Redis處理的每一個寫命令都記錄在AOF文件(類似操作日志文件) 配置

默認(rèn)關(guān)閉,修改redis.conf開啟 記錄頻率的三種方式

always(立刻記錄) everysec(每隔一秒記錄) no(由操作系統(tǒng)決定) 混合持久化

結(jié)合了 RDB 和 AOF 持久化的優(yōu)點(diǎn),開頭為 RDB 的格式,使得 Redis 可以更快的啟動,同時結(jié)合 AOF 的優(yōu)點(diǎn),有減低了大量數(shù)據(jù)丟失的風(fēng)險。 缺點(diǎn)是可讀性差,兼容性差

Redis主從架構(gòu)

搭建主從集群,實(shí)現(xiàn)讀寫分離

全量同步:master將完整的內(nèi)存數(shù)據(jù)生成RDB,發(fā)送RDB到slave后。后續(xù)命令則記錄在repl_baklog,逐個發(fā)送給slave 增量同步:slave提交自己的offset到master,master獲取repl_backlog中從offset之后命令給slave

主從數(shù)據(jù)同步流程

slave節(jié)點(diǎn)請求增量同步 master判斷replid ,如果不一致拒絕增量 slave情況數(shù)據(jù),加載master的RDB master將RDB期間的命令記錄在repl_baklog,并持續(xù)將log中的命令發(fā)送給slave slave執(zhí)行接收到的命令,并與master保持同步

什么時候執(zhí)行全量同步

slave節(jié)點(diǎn)第一次連接master的時候 slave節(jié)點(diǎn)斷開時間太久,repl_baklog中的offset已經(jīng)被覆蓋的時候

Redis哨兵

哨兵是Redis提供的一種利用心跳機(jī)制監(jiān)聽主節(jié)點(diǎn)是否存活的機(jī)制。

如果主節(jié)點(diǎn)掛了,通過判斷slave的slave-priority選舉一個新的。

分片集群

集群中多個master,每個master保持不同數(shù)據(jù)。

就是將多個Redis組合成了一個大的。

Redis會把每個master節(jié)點(diǎn)映射到0-16383供16384個插槽上(hash slot),查看集群信息就能看到。

Redis如何判斷某個key應(yīng)該在哪個實(shí)例?

將16384個插槽分配到不同的實(shí)例中 根據(jù)key的有效部分計算hash值,對16384取余 余數(shù)作為插槽,尋找插槽所在實(shí)例

多級緩存

JVM進(jìn)程緩存

使用Caffeine,利用JVM的進(jìn)程緩存。

Caffeine 的3中緩存淘汰策略:

基于容量 基于時間 基于對象引用。

設(shè)置對象為 軟引用或弱引用,利用GC來回收緩存數(shù)據(jù)。性能較差,不建議使用。

Nginx-反向代理緩存

在服務(wù)端,可以利用反向代理(如Nginx)設(shè)置本地緩存。當(dāng)請求到達(dá)Nginx時,它會首先檢查本地是否有請求的數(shù)據(jù),如果有則直接返回,避免了到達(dá)應(yīng)用服務(wù)器的請求。

Canal

使用Canal實(shí)現(xiàn)數(shù)據(jù)一致性

Redis鍵值設(shè)計

一般約定:

基本格式:[業(yè)務(wù)名稱]:[數(shù)據(jù)名]:[id] 長度不超過44字節(jié) 不包括特殊字符

拒絕BigKey,

key本身數(shù)據(jù)量過大:一個string類型的key,值為5MB key中成員數(shù)過多:一個zset類型的key,成員數(shù)量為:10000個 key中成員數(shù)據(jù)量過大:一個hash類型的key,成員數(shù)量雖只有1000個,但這個value的總大小為100MB

推薦key值:

單個key的value小于10KB 對于集合類型的key,建議元素數(shù)量為小于1000

bigKey危害:

執(zhí)行對BigKey讀的時候,少量的QPS可能導(dǎo)致帶寬使用占滿 導(dǎo)致數(shù)據(jù)傾斜,bigkey所在Redis實(shí)例內(nèi)存遠(yuǎn)超其他實(shí)例 可能運(yùn)算耗時過久,導(dǎo)致主線程阻塞

批處理優(yōu)化

Mset(處理數(shù)據(jù)類型有限)

mset hmset Pipeline(可以對復(fù)制數(shù)據(jù)類型的批處理需要) @Test

void testPipeline(){創(chuàng)建管道

? ?Pipeline pipeline = jedis.pipelined();

? ?for(int i=1;i <= 100000; i++){

? ? ? ?//放入命令到管道

? ? ? ?pipeline.set("test:key_" + i,"value_"+i);

? ? ? ?if(i % 1000 == 0){

? ? ? ? ? ?//批量執(zhí)行

? ? ? ? ? ?pipeline.sync();

? ? ? }

? }

}

集群下數(shù)據(jù)處理

使用Spring提供的stringRedisTemplate就行,底層使用的是并行slot

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

動態(tài)字符串SDS

具備自動擴(kuò)容的能力。

結(jié)構(gòu):

len:字符串字節(jié)數(shù) alloc:申請的總字節(jié)數(shù) flags:不同的SDS頭類型,用來控制頭的大小 buf:具體的字符串

申請空間策略:

當(dāng)新字符串小于1M,則新空間擴(kuò)展后為字符串長度的兩倍+1 當(dāng)新字符串大于1M,則新空間為擴(kuò)展后字符串長度 + 1M +1。(稱為內(nèi)存預(yù)分配)

SDS是一種由C語言實(shí)現(xiàn)的動態(tài)字符串,具有空間預(yù)分配和惰性釋放空間的特點(diǎn)

IntSet

Inset是Redis中set集合的一種實(shí)現(xiàn)方式 基于整形數(shù)組來實(shí)現(xiàn),并具備長度可變、有序等特性。(適合使用于數(shù)據(jù)量不多的情況)

結(jié)構(gòu):

encoding:編碼方式 length:元素個數(shù) contents[]:整數(shù)數(shù)組,保存集合數(shù)據(jù)

總結(jié):

Redis確保Intset元素唯一、有序 具備類型升級機(jī)制(升級編碼方式到合適大?。墒?nèi)存空間 底層采用二分查詢

intset是一種元素全部都是整形的set集合,具有對新增數(shù)據(jù)判斷升級、底層采用二叉查找數(shù)據(jù)、保證數(shù)據(jù)有序且唯一的特點(diǎn)

Dict

實(shí)現(xiàn)了鍵值的映射關(guān)系

組成部分:哈希表(dictht:數(shù)組+鏈表)、哈希節(jié)點(diǎn)(DictEntry)、字典(Dict)

dictEntry結(jié)構(gòu):

key:鍵 v:值 struct dictEntry *next:下一個Entry指針

dictht(dictHashTable)結(jié)構(gòu):

dictEntry **table:entry類型數(shù)組 size:哈希表大小 sizemask:哈希表大小的掩碼,總等于:size-1 used:entry個數(shù)

dict結(jié)構(gòu):

type:dict類型,內(nèi)置不同的hash函數(shù) privdate:私有數(shù)據(jù),做特殊hash運(yùn)算使用 ht[2]:包含兩個哈希表,一個是當(dāng)前數(shù)據(jù),另一個是空,rehash使用 rehashidx:rehash進(jìn)度,-1為未進(jìn)行 pauserehash:rehash是否暫停,1暫停,0繼續(xù)

擴(kuò)容條件

因?yàn)閐ict中的hashtable是由數(shù)組+單向鏈表實(shí)現(xiàn)。當(dāng)元素過多的時候,會導(dǎo)致哈希沖突;而且鏈表過長,影響查詢效率,所以這個時候就需要擴(kuò)容了。

LoadFactor=used(所有的entry)/size(哈希表大小-1)

下面這兩種情況會擴(kuò)容:

LoadFactor >= 1,并服務(wù)器沒有執(zhí)行bgsave / bgrewriteaof等后臺進(jìn)行時候 LoadFactor > 5

每次擴(kuò)容到2^n

Dict收縮

LoadFactor < 0.1時,進(jìn)行收縮 每次收縮到2^n,但是必須大于 4

rehash

因?yàn)槲覀冎罃U(kuò)容還是收縮都要創(chuàng)建一個新的哈希表,但是這會導(dǎo)致size和sizemask變化。 所以必須對哈希表中每個key重新計算索引,插入新的哈希表中,這個過程就叫rehash

rehash過程:

計算哈希表大小 realeSize(應(yīng)分配的哈希表大?。?/p>

擴(kuò)容:realeSize為 大于等于dict.ht[0].used + 1的新的2^n 收縮:同上,但是是小于等于,但不能小于4 申請內(nèi)存空間并創(chuàng)建一個新dictht 設(shè)置dict.rehashidx=0,標(biāo)志rehash的開始 重新對舊hash表中的數(shù)據(jù)進(jìn)行hash求值,并復(fù)制到新hash表中 切換hash表,并釋放舊哈希表中的內(nèi)存空間

漸進(jìn)式rehash:(因?yàn)橐淮涡园徇w哈希表可能出現(xiàn)阻塞情況,所以可以采用漸進(jìn)式,將一步分為多步實(shí)現(xiàn))

漸進(jìn)式rehash相對普通的rehash而言就是,在數(shù)據(jù)遷移的時候,rehash是一次性的操作,而漸進(jìn)式rehash是通過客戶端請求過程中同時進(jìn)行遷移操作 在漸進(jìn)式rehash搬遷數(shù)據(jù)的時候,如果要查詢數(shù)據(jù),是對兩個hash表中進(jìn)行查詢

ziplist

ziplist是一種類似雙端隊(duì)列的設(shè)計,可以在頭尾兩端進(jìn)行加/減元素操作,然后他存儲的方式是一種連續(xù)內(nèi)存的方式,當(dāng)前元素記錄上一個元素的長度,可以根據(jù)元素的type類型區(qū)分是字符串還是數(shù)字,然后選擇是全數(shù)字的ziplist還是全字符串的。

ziplist結(jié)構(gòu):

zlbytes:記錄整個壓縮列表占用內(nèi)存字節(jié)數(shù) zltail:記錄壓縮列表表尾部節(jié)點(diǎn)距離壓縮列表的起始地址有多少字節(jié)。通過這個偏移量,可以確定表尾節(jié)點(diǎn)的地址。 zlen:記錄了壓縮列表包含的節(jié)點(diǎn)數(shù)量。 entry:壓縮列表包含的各個節(jié)點(diǎn),節(jié)點(diǎn)的長度由字節(jié)保存的內(nèi)容決定。 zlend:特殊值OxFF(十進(jìn)制 255),用于標(biāo)記壓縮列表的末端

entry結(jié)構(gòu):(整個entry字節(jié)數(shù)=前節(jié)點(diǎn)長度 + 編碼 + 當(dāng)前節(jié)點(diǎn)內(nèi)容)

previous_entry_length:前一節(jié)點(diǎn)長度,占1或5個字節(jié)

如果前一節(jié)點(diǎn)長度小于254字節(jié),則采用1個字節(jié)保存這個長度值 大于254字節(jié),用5個字節(jié) encoding:編碼屬性,記錄content的數(shù)據(jù)類型(字符串/整數(shù))以及長度。占用1/2/5個字節(jié) contents:負(fù)責(zé)保存節(jié)點(diǎn)的數(shù)據(jù),可以是字符串或整數(shù)

編碼:

字符串:編碼是以 “00”、“01”、“10”開頭 數(shù)字:“11”開始,且encoding固定占用1個字節(jié)

問題:連鎖更新 => 導(dǎo)致內(nèi)存連續(xù)被申請喝銷毀

QuickList

用來解決ziplist連續(xù)空間、無法存儲大量數(shù)據(jù)、數(shù)據(jù)拆分后分散不易管理的問題。

quicklist是一個雙端鏈表,每個節(jié)點(diǎn)都是一個ziplist。

限制ziplist的entry數(shù)量:Redis提供了一個list-max-ziplist-size的配置項(xiàng),用來限制ziplist的entry過多。

-1:不超過4kb -2:8 -3:16 -4:32 -5:64 限制ziplist的大?。簈uicklist還可以通過配置list-compress-depth進(jìn)行對ziplist做壓縮

0:特殊值,不壓縮 1:首尾1個節(jié)點(diǎn)不壓縮,中間節(jié)點(diǎn)壓縮 2:首尾2個節(jié)點(diǎn)不壓縮,中間節(jié)點(diǎn)壓縮 。。。同上類推

QuickListNode結(jié)構(gòu):

QuickListNode *prev:前一節(jié)點(diǎn)指針 QuickListNode *next:后一節(jié)點(diǎn)指針 char *zl:當(dāng)前節(jié)點(diǎn)的ziplist指針 sz:當(dāng)前節(jié)點(diǎn)的ziplist的字節(jié)大小 count:當(dāng)前節(jié)點(diǎn)的ziplist的entry個數(shù) encoding:編碼(1:ziplist,2:lzf壓縮模式) container:數(shù)據(jù)容器類型(預(yù)留)1:其他,2:ziplist ...

quicklist結(jié)構(gòu):

head:頭節(jié)點(diǎn)指針 tail:尾節(jié)點(diǎn)指針 count:所有ziplist的entry的數(shù)量 len:ziplist總數(shù)量 fill:ziplist的entry上限 compress:首尾不壓縮節(jié)點(diǎn)數(shù)量 ...

總結(jié)

我的理解:

quicklist是一種用來解決ziplist連續(xù)存儲空間、無法存儲超大容量數(shù)據(jù)、數(shù)據(jù)拆分不易管理而提出的一種數(shù)據(jù)類型,是一個雙端鏈表,節(jié)點(diǎn)上存儲的是一個ziplist。

skiplist

skiplist是一種特殊的鏈表,具有升序排序存儲、節(jié)點(diǎn)包含多個不同跨度的指針的特點(diǎn)。

zskiplistNode結(jié)構(gòu):

ele:節(jié)點(diǎn)存儲的值 score:節(jié)點(diǎn)分?jǐn)?shù)。用來排序、查詢 backword:前一個節(jié)點(diǎn)指針 level[] :多級索引數(shù)組

forward:下一個節(jié)點(diǎn)指針 span:索引跨度

zskiplist:

header,tail:頭尾指針 length:節(jié)點(diǎn)數(shù)量 level:索引層級,默認(rèn)1,最多32級

總結(jié):

個人理解:

skiplist是一種按score值升序排序存儲的雙向鏈表,對這個鏈表按照全局固定的一個span值進(jìn)行劃分一個索引層次,可以用這個層次來加速查詢

RedisObject

通過對上述的任意數(shù)據(jù)類型的鍵值封裝成一個RedisObject形成Redis的基本數(shù)據(jù)類型。

結(jié)構(gòu):

type:對象類型。string、hash、list、set、zset(占4bit) encoding:底層編碼方式,11種(占4bit) lru: refcount:對象引用計數(shù)器,計數(shù)器為0時,無人引用,可被回收 ptr:指向?qū)嶋H的數(shù)據(jù)存儲空間

上述的頭部已經(jīng)占用了16個字節(jié)了。

這就是為什么存儲大容量數(shù)據(jù)不用string類型的原因了,一個string數(shù)據(jù)就多占用16個字節(jié)

11種編碼方式:

對應(yīng)著不同數(shù)據(jù)類型采用的不同編碼:

Redis的5種基本數(shù)據(jù)類型

string

采用的編碼:int、embstr、raw

基本編碼方式是raw,基于動態(tài)字符串(SDS)實(shí)現(xiàn),存儲上限512MB 當(dāng)SDS長度小于44字節(jié),則采用embstr編碼。 當(dāng)存儲的字符串是整數(shù)值,并在long_max范圍,采用int編碼

直接將數(shù)據(jù)保存在RedisObject的ptr指針位置(剛好有8個字節(jié)大?。?,不需要SDS了

list

采用的編碼

3.2之前:linkedlist + ziplist 3.2之后:quicklist

set

采用的編碼:intset、ht

當(dāng)存儲的所有數(shù)據(jù)都是整數(shù)的時候,并且元素的數(shù)量不超過set-max-intset-entries,set會采用intset這種編碼節(jié)省空間 其他時候采用ht編碼(Dict),key用來存儲元素,value統(tǒng)一為null(雖然這個value為null有點(diǎn)浪費(fèi),但是整體來說還是值得的)

zset

采用的編碼:ziplist、ht、skiplist

因?yàn)閦set的特點(diǎn):鍵值存、鍵必須唯一、可排序

通過skiplist + ht(Dict)實(shí)現(xiàn):

skiplist:可排序,可存儲score喝ele值(member) ht(Dict):存儲鍵值,根據(jù)key找value

typedef struct zset{

? ?dict *dict;

? ?zskiplist *zls;

}

當(dāng)元素數(shù)量不多的時候,ht+skiplist的優(yōu)勢不明顯,而且更耗內(nèi)存。這個時候會通過ziplist來節(jié)省內(nèi)存。

要滿足以下兩個條件:

元素數(shù)量小于zset_ziplist_entries,默認(rèn)128 每個元素都小于 zset_max_ziplist_value字節(jié),默認(rèn)64

ziplist本身沒有鍵值存儲、沒有排序功能,這個時候要功能代碼進(jìn)行實(shí)現(xiàn):

ziplist是連續(xù)內(nèi)存,所以score和ele是緊湊一起的兩個entry,ele前,score后 score越小越近隊(duì)首,score越大越接近隊(duì)尾,按score升序排序

hash

采用的編碼:ziplist、ht

hash底層跟zset基本一致,只需把排序有關(guān)的skiplist去掉即可:

hash默認(rèn)采用ziplist,節(jié)省內(nèi)存,相鄰的兩個entry分別保存field 和 value 數(shù)據(jù)較大時,hash轉(zhuǎn)ht編碼(Dict)。觸發(fā)條件:

ziplist的元素數(shù)量超過了hash-max-ziplist-entries(默認(rèn)512) ziplist種任意的entry大小超過了hash-max-ziplist-value(默認(rèn)64字節(jié))

總結(jié)

string

intset:全整數(shù)+數(shù)據(jù)小時 embstr:小于44字節(jié) raw默認(rèn)這種,采用SDS,最大512字節(jié) list

3.2前:看情況使用ziplist和linkedlist(大)實(shí)現(xiàn) 3.2后:統(tǒng)一使用quicklist實(shí)現(xiàn) set

intset:全數(shù)字 + 不超多一個闕值 dict zset

ziplist:數(shù)據(jù)量小時=> 頭小,尾大;前ele,后score skiplist(排序) + dict(唯一) hash

ziplist:數(shù)據(jù)量小時=> 頭小,尾大;前field,后value dict(唯一)

Linux網(wǎng)絡(luò)模型

在Linux操作系統(tǒng)中,用戶是不是沒有直接的權(quán)限去操作文件的,而是通過調(diào)用系統(tǒng)內(nèi)核的接口實(shí)現(xiàn)調(diào)用的。這里分為用戶空間和內(nèi)核空間兩個概念了。

阻塞IO

要讀取數(shù)據(jù),發(fā)現(xiàn)沒有數(shù)據(jù),就阻塞等待。 在等待數(shù)據(jù)階段和拷貝數(shù)據(jù)階段這兩個階段都在阻塞。

非阻塞IO

通過反復(fù)輪詢請求訪問內(nèi)核,看看是否有數(shù)據(jù)。 等待階段是非阻塞的(如果沒有數(shù)據(jù)就返回一個錯誤代碼),拷貝數(shù)據(jù)這個階段是阻塞的 非阻塞IO的關(guān)鍵在于減少阻塞等待的時間,使得線程或進(jìn)程在等待IO操作完成的同時可以去做其他事情

IO多路復(fù)用

在Linux系統(tǒng)中,開啟了許多個FD,通過使用一個單線程檢測各個FD是否完成,進(jìn)行返回結(jié)果。

fd(文件描述符):Linux系統(tǒng)中任意一個資源的打開,包括socket。

實(shí)現(xiàn)方式

select模式

初始化fd_set

定義個存儲fd的集合:fd_set 情況fd_set 將fd添加到fd_set中 select函數(shù)的調(diào)用

select函數(shù)調(diào)用,將fd_set拷貝到內(nèi)核空間中 遍歷fd_set,沒有就緒則休眠 等待數(shù)據(jù)就緒被喚醒或超時 處理結(jié)果

檢查返回值,看看有多少的fd準(zhǔn)備好了 集合遍歷,看看指定的fd是否在就緒集合中 處理就緒的fd poll模式

初始化

創(chuàng)建pollfd數(shù)組,并添加關(guān)注的fd信息,數(shù)組大小自定義 調(diào)用poll函數(shù)

調(diào)用poll函數(shù),將pollfd數(shù)組拷貝到內(nèi)核中,轉(zhuǎn)無上限鏈表存儲 遍歷fd,判斷是否就緒 數(shù)據(jù)就緒/超時,拷貝pollfd數(shù)組到用戶空間,返回fd就緒個數(shù)n 處理結(jié)果

用戶進(jìn)行判斷n是否大于0 大于0,遍歷poll數(shù)組,找到就緒的fd epoll模式

初始化 epoll_create()

在內(nèi)核空間創(chuàng)建一個eventpoll的結(jié)構(gòu)體 結(jié)構(gòu)體包括:rb_root rbr紅黑樹,list_head rdlist就緒列表 添加fd epoll_ctl()

添加fd添加到epoll的rbr紅黑樹中,并設(shè)置ep_poll_callback 當(dāng)callback觸發(fā)時,把對應(yīng)的FD添加到rdlist就緒列表中 檢查rdlist列表是否為空,不為空則直接返回就緒的FD數(shù)量 epoll_wait()

上述小結(jié):

select模式的問題:

能監(jiān)聽的FD不超過1024 每次select都需要把要監(jiān)聽的fd拷貝到內(nèi)核空間 每次都要遍歷所有的fd來判斷就緒狀態(tài)

poll模式的問題

poll利用鏈表解決了select監(jiān)聽fd上限問題,但仍需遍歷所有的fd。如果監(jiān)聽較多,性能下降

epoll解決上述問題:

基于epoll實(shí)例中,紅黑樹保存監(jiān)聽fd,理論上無上限,增刪改查性能較高,性能不隨著監(jiān)聽的fd數(shù)量增多而下降 每個fd只需執(zhí)行一次epoll_ctl添加到紅黑樹,之后epol_wait無需傳遞任何參數(shù),無需重復(fù)拷貝fd到內(nèi)核空間

事件通知機(jī)制

當(dāng)rdlist中有數(shù)據(jù)可讀時,調(diào)用epoll_wait可以得到通知,得到事務(wù)通知的模式有以下兩種:

levelTriggered(LT):當(dāng)FD有數(shù)據(jù)可讀時,會重復(fù)通知多次,知道數(shù)據(jù)處理完成(默認(rèn)) EdgeTriggered(ET):當(dāng)FD有數(shù)據(jù)可讀時,只會通知一次,不管是數(shù)據(jù)是否完成

ET模式避免了LT模式可能出現(xiàn)的驚群現(xiàn)象 ET模式最好結(jié)合非阻塞IO讀取FD數(shù)據(jù),相對比LT復(fù)雜點(diǎn),但是效率更高

驚群現(xiàn)象:當(dāng)多個套接字(sockets)同時處于等待事務(wù)的狀態(tài),但實(shí)際上只有一個套接字會接收到數(shù)據(jù)通知時所發(fā)生的情況

Web服務(wù)中流程

信號驅(qū)動IO

寫真正的實(shí)現(xiàn)了非阻塞,但讀時候,仍有阻塞。

用戶應(yīng)用與內(nèi)核進(jìn)行了一個綁定,如果沒有數(shù)據(jù),用戶應(yīng)用可以去做其他的事,但是當(dāng)有數(shù)據(jù)的時候,會發(fā)送一個通知給用戶應(yīng)用,讓他來處理事務(wù)

異步IO

用戶應(yīng)用只用調(diào)用,內(nèi)核會自動去做完一切,到最后通知。

但是有一個問題:如果在高并發(fā)請求下,瘋狂的調(diào)用,直接會導(dǎo)致崩潰。所以需要進(jìn)行調(diào)用限流,但是這個限流實(shí)現(xiàn)還是有點(diǎn)小麻煩的。

總結(jié)

只有異步IO是異步的,其他都是同步。

Redis網(wǎng)絡(luò)模型

Redis是單線程還是多線程?

Redis核心業(yè)務(wù)部分(命令處理)是單線程

處理客戶端請求、執(zhí)行命令時,Redis 主要依賴于單個線程來完成。這種設(shè)計簡化了并發(fā)控制,提高了 Redis 在處理大量連接和請求時的效率。 整體上Redis 是多線程

在持久化過程中,執(zhí)行IO操作會利用到多線程 在某些高級特性如 Redis Sentinel、Redis Cluster 中,可能會使用多個線程來處理監(jiān)視、故障轉(zhuǎn)移等任務(wù)。 在一些 Redis 模塊中,可能會引入多線程以支持特定的功能或提高性能 持久化操作或者部分計算密集型操作,Redis 會使用額外的線程來執(zhí)行這些任務(wù),以避免阻塞主線程。

為什么Redis要采用單線程?

簡化設(shè)計和實(shí)現(xiàn):單線程模型使得 Redis 的設(shè)計和實(shí)現(xiàn)變得相對簡單,減少了并發(fā)控制和同步的復(fù)雜性。這降低了開發(fā)和維護(hù)的成本,并且使得 Redis 的代碼更加清晰和易于理解。 多線程不會提高太大的性能提升:拋開持久化不說,Redis是純內(nèi)存操作,執(zhí)行速度非常快,它的性能瓶頸是網(wǎng)絡(luò)延遲,而不是執(zhí)行速度,因此多線程并不會帶來巨大的性能提升。 高效利用CPU:雖然 Redis 是單線程的,但它可以利用多個 CPU 核心,并行地處理多個客戶端請求。通過使用非阻塞 I/O 和事件驅(qū)動的方式,Redis 能夠高效地利用 CPU 資源,并在處理高并發(fā)時表現(xiàn)出色。 減少上下文切換和內(nèi)存開銷:單線程模型減少了線程創(chuàng)建和銷毀的開銷,以及線程上下文切換的成本,從而提高了 Redis 在高并發(fā)環(huán)境下的性能和穩(wěn)定性。此外,單線程模型也減少了為每個連接分配線程所需的內(nèi)存開銷。

Redis單線程網(wǎng)絡(luò)模型流程

網(wǎng)絡(luò)模型引入多線程

Redis處理時候速度非??欤窃贗O網(wǎng)絡(luò)請求的速度沒有那么快,容易出現(xiàn)網(wǎng)絡(luò)阻塞,所以在網(wǎng)絡(luò)讀/寫的時候加入多線程提高系統(tǒng)效率。

Redis內(nèi)存策略

過期key處理

Redis本身是一個key-value內(nèi)存存儲的數(shù)據(jù)庫——redisDb。 key,value都保存在Dict結(jié)構(gòu)中(兩個Dict)

一個Dict存儲key-value 一個記錄key-TTL

結(jié)構(gòu):

dict:存儲key-value expires:存儲key的TTL

Redis是如何知道一個key是否過期的?

利用兩個Dict分別記錄key-value和key-ttl 有兩種策略發(fā)現(xiàn)是否過期,并將該過期key刪除

惰性刪除:在訪問一個key對象時,檢查該key的存活事件,如果已過則刪除 周期刪除:周期性抽樣部分過期key,然后執(zhí)行刪除

(了解即可)SLOW:設(shè)置一個定時任務(wù)serverCron(),按照server.hz頻率執(zhí)行過期key清理 (了解即可)FAST:每個事件循環(huán)前會調(diào)用beforeSleep(),執(zhí)行過期key

內(nèi)存淘汰機(jī)制

內(nèi)存淘汰:當(dāng)Redis內(nèi)存使用達(dá)到闕值的時候,Redis主動挑選部分Key刪除釋放更多內(nèi)存。

內(nèi)存淘汰策略

補(bǔ)充一下lru和lfu:

lru:最近最少使用。用當(dāng)前事件減去最后一次訪問時間,值越大越先淘汰 lfu:最少頻率使用。會統(tǒng)計每個key的訪問頻率,值越小淘汰越優(yōu)先

noeviction:不淘汰任何key,但是內(nèi)存滿了不允許寫入新數(shù)據(jù)(默認(rèn)) ttl:淘汰最小TTL值

volatile-ttl:對設(shè)置了TTL的key,淘汰最小的TTL值 random:隨機(jī)

volatile-random:對設(shè)置了TTL的key,隨機(jī)進(jìn)行淘汰 allkeys-random:對所有的key,隨機(jī)進(jìn)行淘汰 lru:最近最少使用的值(淘汰掉最近一段時間內(nèi)最少被訪問的數(shù)據(jù))

volatile-lru:對設(shè)置了TTL的key,采用lru進(jìn)行淘汰 allkeys-lru:對所有的key,采用lru進(jìn)行淘汰 lfu:最少頻率使用(淘汰訪問頻率低的)

volatile-lfu:對設(shè)置了TTL的key,采用lfu進(jìn)行淘汰 allkeys-lfu:對所有的key,采用lfu進(jìn)行淘汰

補(bǔ)充:

Redis中隊(duì)TTL、LRU、LFU策略使用的時候,使用的是抽樣部分淘汰

柚子快報邀請碼778899分享:Redis進(jìn)階知識個人匯總

http://yzkb.51969.com/

好文鏈接

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19115881.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄