Redis特性解讀


我的個(gè)人主頁:螞蟻的寶藏

傳統(tǒng)數(shù)據(jù)庫遵循ACID原則,而NOSQL遵循CAP原則。

Consistency(一致性): 所有節(jié)點(diǎn)在同一時(shí)間具有相同的數(shù)據(jù)
Availability(可用性):集群中一部分節(jié)點(diǎn)失效后,集群整體保證響應(yīng)客服端的讀寫請求
Partition tolerance(分區(qū)容災(zāi)性):系統(tǒng)中任意信息的丟失或失敗不會影響系統(tǒng)繼續(xù)運(yùn)行。

任何時(shí)候,最多滿足以上兩點(diǎn),在分布式存儲中,分區(qū)容災(zāi)性是必須的,所以在一致性和可用性上要做出權(quán)衡。redis在一致性上做出了妥協(xié),采用結(jié)果最終一致性的弱化處理數(shù)據(jù)異步復(fù)制。

redis演變

復(fù)制

redis提供復(fù)制功能,用戶可以通過復(fù)制master來創(chuàng)建多個(gè)slave。只要主從服務(wù)器之間通信正常,會保持相同的數(shù)據(jù),master會一直將自身的數(shù)據(jù)更新至slave。解決了master的讀壓力。

哨兵

redis sentinel 在分布式系統(tǒng)中,監(jiān)控主從服務(wù)器,在master下線,會自動進(jìn)行故障轉(zhuǎn)移,保證了系統(tǒng)的高可用。

集群(proxy)

通過增加proxy層來進(jìn)行數(shù)據(jù)分片,減輕redis的寫壓力。但是proxy層無法保證高可用,維護(hù)成本增加。

集群(直連型)

去除proxy層,無中心架構(gòu);通過選舉制實(shí)現(xiàn)故障轉(zhuǎn)移,完成slave到master的角色轉(zhuǎn)換;節(jié)點(diǎn)可動態(tài)擴(kuò)張;通過增加slave節(jié)點(diǎn)實(shí)現(xiàn)高可用;數(shù)據(jù)按照slot存儲,節(jié)點(diǎn)數(shù)據(jù)可共享。

redis數(shù)據(jù)結(jié)構(gòu)

redis以 key-value 鍵值對 作為存儲方式。支持多種數(shù)據(jù)結(jié)構(gòu)。

String
string是redis使用最多的數(shù)據(jù)結(jié)構(gòu)之一,value大小不能超過512M,set的時(shí)候,可以不用引號。
值可以是字符串,整數(shù),浮點(diǎn)數(shù)。
若值為數(shù)字,做運(yùn)算時(shí),redis會自動進(jìn)行轉(zhuǎn)換。

命令 說明
SET key value 定義key并賦值
GET key 獲取key的值
DEL key 刪除key
APPEND key value 末尾追加,字符串拼接
STRLEN key 獲取字符串長度
INCR key 自增
DECR key 自減
INCRBY key increment 按指定步長增長
DECRBY key increment 按指定步長減少
SETEX key seconds value 同時(shí)設(shè)置過期時(shí)間,同EXPIRE,可使用TTL查看剩余時(shí)間

List
鏈表上的每個(gè)節(jié)點(diǎn)包含一個(gè)字符串。鏈表的兩端都可以進(jìn)行讀寫。

命令 說明
LPUSH key value 向鏈表左端添加元素value
RPUSH key value 向鏈表右端添加元素value
LPOP key 從鏈表左側(cè)讀取并移除元素
RPOP key 從鏈表右側(cè)讀取并移除元素
LINDEX key index 按index讀取vaule
LRANGE key start stop 讀取指定范圍的元素
BRPOP key[key ...] timeout 阻塞的方式從鏈表右側(cè)彈出元素,如果元素為空,阻塞等待,直到超時(shí)或者有值返回
BLPOP key[key ...] timeout 阻塞的方式從鏈表右側(cè)彈出元素,如果元素為空,阻塞等待,直到超時(shí)或者有值返回

Set
無序且無重復(fù)的字符串集合

常用命令:

命令 說明
SADD key value 向key中添加元素value,成功返回1,失敗返回0
SREM key value 從key中移除元素value,成功1,失敗0
SMEMBERS key 列出key中所有元素
SISMEMBER key value 判斷key中是否存在元素value,沒找到0

zset
有序的set集合,通過浮點(diǎn)數(shù)score來實(shí)現(xiàn)。
元素a,b,若a.score>b.score,則a>b;若a.score=b.score,a>b,則a>b。

命令 說明
ZADD key score member 向key集合中插入memeber,設(shè)置score
ZRANGE key start stop 讀取指定范圍類元素
ZRANGEBYSCORE key min man 按照score的范圍讀取元素
ZREM key member 移除元素

hash
包含key,value的散列表。

命令 說明
HMSET key field value [field value ...] 添加值
HGET key field 取值
HMGET key field [field ...] 取值
HGETALL key 獲取所有元素
HDEL key field [field ...] 刪除指定字段

事務(wù)

因?yàn)閞edis是單線程來處理所有client的請求,所以redis對事務(wù)的處理比較簡單,通過一個(gè)類似阻塞隊(duì)列的東西保證一個(gè)client發(fā)起的事務(wù)中的命令可以順序執(zhí)行,中間不會插入其他client的命令。

通過 EXEC 命令來開啟一個(gè)事務(wù),DISCARD取消事務(wù),EXEC結(jié)束事務(wù)

發(fā)布訂閱

發(fā)布訂閱(pub/sub)是類似觀察者模式的一種消息通信模式,發(fā)送者(pub)發(fā)送消息,訂閱者(sub)接收消息。

image.png-44.1kB
image.png-44.1kB

ps.網(wǎng)上找的圖

SUBSCRIBE 訂閱主題,開啟通道,獲取消息
PUBLISH 推送消息
UNSUBSCRIBE 取消主題

持久化

為了防止服務(wù)宕機(jī)內(nèi)存數(shù)據(jù)丟失,redis提供了三種持久化方式:RDB(deafult),AOF,RDB和AOF同時(shí)使用。

RDB:

定時(shí)調(diào)用 rdbSave 函數(shù),將內(nèi)存數(shù)據(jù)寫入一個(gè)dump.rdb,如果文件存在,替換。
操作 rdbSave 函數(shù)有兩種命令,SAVE和BGSAVE
SAVE命令會直接調(diào)用rdbSave函數(shù),在RDB文件保存期間,主進(jìn)程會被阻塞,服務(wù)端無法處理客戶端請求,保存完成,喚醒主線程。
BGSAVE命令會先fork一個(gè)子進(jìn)程,由子進(jìn)程調(diào)用 rdbSave 函數(shù),不會阻塞主進(jìn)程,服務(wù)端仍可服務(wù)客戶端,保存完成,子進(jìn)程會向主進(jìn)程發(fā)送通知。
在redis服務(wù)啟動或重啟時(shí),會調(diào)用 rdbLoad 函數(shù),加載磁盤中的RDB文件到內(nèi)存中。

+-------+-------------+-----------+-----------------+-----+-----------+
| REDIS | RDB-VERSION | SELECT-DB | KEY-VALUE-PAIRS | EOF | CHECK-SUM |
+-------+-------------+-----------+-----------------+-----+-----------+

                  |<-------- DB-DATA ---------->|
image.png-11.6kB
image.png-11.6kB

保存策略:
save 900 10 #900s內(nèi)超過10個(gè)key被修改,發(fā)起快照保存。

AOF:
append-only-file,以協(xié)議(RESP)文本的方式,把數(shù)據(jù)庫的命令操作參數(shù)追加到aof文件中。
這個(gè)過程分為三步:
1.命令傳播:Redis 將執(zhí)行完的命令、命令的參數(shù)、命令的參數(shù)個(gè)數(shù)等信息發(fā)送到 AOF 程序中。
2.緩存追加:AOF 程序根據(jù)接收到的命令數(shù)據(jù),將命令轉(zhuǎn)換為網(wǎng)絡(luò)通訊協(xié)議的格式,然后將協(xié)議內(nèi)容追加到服務(wù)器的 AOF 緩存中。
3.文件寫入和保存:AOF 緩存中的內(nèi)容被寫入到 AOF 文件末尾,如果設(shè)定的 AOF 保存條件被滿足的話, fsync 函數(shù)或者 fdatasync 函數(shù)會被調(diào)用,將寫入的內(nèi)容真正地保存到磁盤中。
AOF支持三種保存模式:
1.AOF_FSYNC_NO :不保存。
2.AOF_FSYNC_EVERYSEC :每一秒鐘保存一次。(不阻塞主進(jìn)程)
3.AOF_FSYNC_ALWAYS :每執(zhí)行一個(gè)命令保存一次。(阻塞主進(jìn)程)

參考文獻(xiàn) -- 《Redis設(shè)計(jì)與實(shí)現(xiàn)》

image.png-16.9kB
image.png-16.9kB

可以看到 rdb文件中存儲的數(shù)據(jù),aof文件中存儲的是命令+數(shù)據(jù),而且aof的文件可讀性更高。
除此之外,AOF的更新頻率高于RDB,優(yōu)先加載aof。

復(fù)制

redis的復(fù)制方式有兩種,一種是主(master)-從(slave),一種是從(slave)-從(slave)。

image.png-19.5kB
image.png-19.5kB

配置方式:

# 復(fù)制一份配置文件 cp redis.conf slave.conf
# 修改slave的配置 slaveof ip port
# 修改master的配置 bind 0.0.0.0
# 啟動slave ./redis-server ../slave.conf &

集群

在redis集群中,引入了hash槽-slot的概念。
集群中的節(jié)點(diǎn)node,共同分配16384個(gè)slot,所以集群中節(jié)點(diǎn)最多只能有16384個(gè),所有的key都對映射到對應(yīng)的slot中。
redisCluster通過CRC16(key)/16384 來計(jì)算key屬于哪個(gè)槽。

通過為每個(gè)node分片不同數(shù)量的slot,按照槽來分片,可以控制不同節(jié)點(diǎn)的數(shù)據(jù)量和請求數(shù)。

redisCluster的特點(diǎn):
1.節(jié)點(diǎn)自動發(fā)現(xiàn)
2.slave->master 選舉,集群容錯(cuò)
3.支持rehsard在線分片
4.節(jié)點(diǎn)直連型,不需要proxy層
5.所有節(jié)點(diǎn)彼此互連(ping-pong)

數(shù)據(jù)遷移

當(dāng)我們需要新增節(jié)點(diǎn)時(shí),只需要從以往節(jié)點(diǎn)中分配部分slot到新節(jié)點(diǎn);需要?jiǎng)h除節(jié)點(diǎn)時(shí),先把該節(jié)點(diǎn)的slot轉(zhuǎn)移到其他節(jié)點(diǎn),然后刪除即可。這個(gè)功能極大方便了集群的線性擴(kuò)展或縮容,并不會造成集群不可用的狀態(tài)。


image.png-14.4kB
image.png-14.4kB

在slot遷移過程中,masterA狀態(tài)為MIGRATING,masterB狀態(tài)為IMPORTING。
真正改變node映射的是鍵空間遷移。

src目錄下的集群管理命令redis-trib.rb支持reshard的手動在線遷移方式。

命令 說明
call 在集群全部節(jié)點(diǎn)上執(zhí)行命令
set-timeout 設(shè)置集群節(jié)點(diǎn)間心跳連接的超時(shí)時(shí)間
del-node 從集群中刪除節(jié)點(diǎn)
reshard 在線遷移slot
check 檢查集群
import 將外部redis數(shù)據(jù)導(dǎo)入集群
add-node 將新節(jié)點(diǎn)加入集群
create 創(chuàng)建集群
info 查看集群信息
fix 修復(fù)集群
rebalance 自動平分集群節(jié)點(diǎn)slot數(shù)量
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容