溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Redis設(shè)計思路總結(jié)

發(fā)布時間:2020-10-25 04:58:18 來源:網(wǎng)絡(luò) 閱讀:313 作者:sxt程序猿 欄目:編程語言

本文從網(wǎng)絡(luò)模型、數(shù)據(jù)結(jié)構(gòu)和內(nèi)存管理、持久化和多機(jī)協(xié)作四個角度對redis的設(shè)計思路進(jìn)行分析。
一.網(wǎng)絡(luò)模型

Redis是典型的基于Reactor的事件驅(qū)動模型,單進(jìn)程單線程,高效的框架總是類似的。網(wǎng)絡(luò)模型與spp的異步模型幾乎一致。

Redis流程上整體分為接受請求處理器、響應(yīng)處理器和應(yīng)答處理器三個同步模塊,每一個請求都是要經(jīng)歷這三個部分。

Redis集成了libevent/epoll/kqueue/select等多種事件管理機(jī)制,可以根據(jù)操作系統(tǒng)版本自由選擇合適的管理機(jī)制,其中l(wèi)ibevent是最優(yōu)選擇的機(jī)制。

Redis的網(wǎng)絡(luò)模型有著所有事件驅(qū)動模型的優(yōu)點,高效低耗。但是面對耗時較長的操作的時候,同樣無法處理請求,只能等到事件處理完畢才能響應(yīng)。所以了解清楚網(wǎng)絡(luò)模型有助于在業(yè)務(wù)中揚(yáng)長避短,減少長耗時的請求,盡可能多一些簡單的短耗時請求發(fā)揮異步模型的最大的威力。

二.數(shù)據(jù)結(jié)構(gòu)和內(nèi)存管理

1.字符串

1.1 內(nèi)存管理方式

動態(tài)內(nèi)存管理方式,動態(tài)方式最大的好處就是能夠較為充分的利用內(nèi)存空間,減少內(nèi)存碎片化,與此同時帶來的劣勢就是容易引起頻繁的內(nèi)存抖動,通常采用“空間預(yù)分配”和“惰性空間釋放”兩種優(yōu)化策略來減少內(nèi)存抖動,redis也不例外。

每次修改字符串內(nèi)容時,首先檢查內(nèi)存空間是否符合要求,否則就擴(kuò)大2倍或者按M增長;減少字符串內(nèi)容時,內(nèi)存并不會立刻回收,而是按需回收。

關(guān)于內(nèi)存管理的優(yōu)化,最基本的出發(fā)點就是浪費(fèi)一點空間還是犧牲一些時間的權(quán)衡,像STL、tcmalloc、protobuf3的arena機(jī)制等采用的核心思路都是“預(yù)分配遲回收”,Redis也是一樣的。

1.2 二進(jìn)制安全

判斷字符串結(jié)束與否的標(biāo)識是len字段,而不是C語言的’\0’,因此是二進(jìn)制安全的。

放心的將pb序列化后的二進(jìn)制字符串存入redis。

簡而言之,通過redis的簡單封裝,redis的字符串的操作更加方便,性能更友好,并且屏蔽了C語言字符串的一些需要用戶關(guān)心的問題。

2.字典(哈希)

字典的底層一定是hash,涉及到hash一定會涉及到hash算法、沖突的解決方法和hash表擴(kuò)容和縮容。

2.1 hash算法

  Redis使用的就是常用的Murmurhash3,Murmurhash算法能夠給出在任意輸入序列下的散列分布性,并且計算速度很快。之前做共享內(nèi)存的Local-Cache的需求時也正是利用了Murmurhash的優(yōu)勢,解決了原有結(jié)構(gòu)的hash函數(shù)散列分布性差的問題。

2.2 hash沖突解決方法

鏈地址法解決hash沖突,通用解決方案沒什么特殊的。多說一句,如果選用鏈地址解決沖突,那么勢必要有一個散列性非常好的hash函數(shù),否則hash的性能將會大大折扣。Redis選用了Murmurhash,所以可以放心大膽的采用鏈地址方案。

3.整數(shù)集合

變長整數(shù)存儲,整數(shù)分為16/32/64三個變長尺度,根據(jù)存入的數(shù)據(jù)所屬的類型,進(jìn)行規(guī)劃。

每次插入新元素都有可能導(dǎo)致尺度升級(例如由16位漲到32位),因此插入整數(shù)的時間復(fù)雜度為O(n)。這里也是一個權(quán)衡,內(nèi)存空間和時間的一個折中,盡可能節(jié)省內(nèi)存。

4.跳躍表

Redis的skilplist和普通的skiplist沒什么不同,都是冗余數(shù)據(jù)實現(xiàn)的從粗到細(xì)的多層次鏈表,Redis中應(yīng)用跳表的地方不多,常見的就是有序集合。

5.鏈表

Redis的鏈表是雙向非循環(huán)鏈表,擁有表頭和表尾指針,對于首尾的操作時間復(fù)雜度是O(1),查找時間復(fù)雜度O(n),插入時間復(fù)雜度O(1)。

三.AOF和RDB持久化

AOF持久化日志,RDB持久化實體數(shù)據(jù),AOF優(yōu)先級大于RDB。

1.AOF持久化

機(jī)制:通過定時事件將aof緩沖區(qū)內(nèi)的數(shù)據(jù)定時寫到磁盤上。

2.AOF重寫

為了減少AOF大小,Redis提供了AOF重寫功能,這個重寫功能做的工作就是創(chuàng)建一個新AOF文件代替老的AOF,并且這個新的AOF文件沒有一條冗余指令。(例如對list先插入A/B/C,后刪除B/C,再插入D共6條指令,最終狀態(tài)為A/D,只需1條指令就可以)

實現(xiàn)原理就是讀現(xiàn)有數(shù)據(jù)庫的狀態(tài),根據(jù)狀態(tài)反推指令,跟之前的AOF無關(guān)。同樣,為了避免長時間耗時,重寫工作放在子進(jìn)程進(jìn)行。

3.RDB持久化

SAVE和BGSAVE兩個命令都是用于生成RDB文件,區(qū)別在于BGSAVE會fork出一個子進(jìn)程單獨(dú)進(jìn)行,不影響Redis處理正常請求。定時和定次數(shù)后進(jìn)行持久化操作。

簡而言之,RDB的過程其實是比較簡單的,滿足條件后直接去寫RDB文件就結(jié)束了。

四.多機(jī)和集群

1.主從服務(wù)器

避免單點是所有服務(wù)的通用問題,Redis也不例外。解決單點就要有備機(jī),有備機(jī)就要解決固有的數(shù)據(jù)同步問題。

1.1 sync——原始版主從同步

Redis最初的同步做法是sync指令,通過sync每次都會全量數(shù)據(jù),顯然每次都全量復(fù)制的設(shè)計比較消耗資源。改進(jìn)思路也是常規(guī)邏輯,第一次全量,剩下的增量,這就是現(xiàn)在的psync指令的活。

1.2 psync

部分重同步實現(xiàn)的技術(shù)手段是“偏移序號+積壓緩沖區(qū)”,具體做法如下:

(1)主從分別維護(hù)一個seq,主每次完成一個請求便seq+1,從每同步完后更新自己seq;

(2)從每次打算同步時都是攜帶著自己的seq到主,主將自身的seq與從做差結(jié)果與積壓緩沖區(qū)大小比較,如果小于積壓緩沖區(qū)大小,直接從積壓緩沖區(qū)取相應(yīng)的操作進(jìn)行部分重同步;

(3)否則說明積壓緩沖區(qū)不能夠cover掉主從不一致的數(shù)據(jù),進(jìn)行全量同步。

本質(zhì)做法用空間換時間,顯然在這里犧牲部分空間換回高效的部分重同步,收益比很大。

2.Sentinel

本質(zhì):多主從服務(wù)器的Redis系統(tǒng),多臺主從上加了管理監(jiān)控,以保證系統(tǒng)高可用性。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI