Redis是什么惠勒?
Redis(Remote Dictionary Server)是一個(gè)使用 C 語(yǔ)言編寫(xiě)的赚抡,高性能非關(guān)系型的鍵值對(duì)數(shù)據(jù)庫(kù)。與傳統(tǒng)數(shù)據(jù)庫(kù)不同的是纠屋,Redis 的數(shù)據(jù)是存在內(nèi)存中的涂臣,所以讀寫(xiě)速度非常快售担,被廣泛應(yīng)用于緩存方向赁遗。Redis可以將數(shù)據(jù)寫(xiě)入磁盤(pán)中,保證了數(shù)據(jù)的安全不丟失灼舍,而且Redis的操作是原子性的吼和。
Redis優(yōu)缺點(diǎn)涨薪?
優(yōu)點(diǎn):
- 基于內(nèi)存操作骑素,內(nèi)存讀寫(xiě)速度快。
- Redis是單線程的刚夺,避免線程切換開(kāi)銷(xiāo)及多線程的競(jìng)爭(zhēng)問(wèn)題献丑。單線程是指網(wǎng)絡(luò)請(qǐng)求使用一個(gè)線程來(lái)處理,即一個(gè)線程處理所有網(wǎng)絡(luò)請(qǐng)求侠姑,Redis 運(yùn)行時(shí)不止有一個(gè)線程创橄,比如數(shù)據(jù)持久化的過(guò)程會(huì)另起線程。
- 支持多種數(shù)據(jù)類(lèi)型莽红,包括String妥畏、Hash、List安吁、Set醉蚁、ZSet等。支持持久化鬼店。
- Redis支持RDB和AOF兩種持久化機(jī)制网棍,持久化功能可以有效地避免數(shù)據(jù)丟失問(wèn)題。
- 支持事務(wù)妇智。Redis的所有操作都是原子性的滥玷,同時(shí)Redis還支持對(duì)幾個(gè)操作合并后的原子性執(zhí)行氏身。
- 支持主從復(fù)制。主節(jié)點(diǎn)會(huì)自動(dòng)將數(shù)據(jù)同步到從節(jié)點(diǎn)惑畴,可以進(jìn)行讀寫(xiě)分離蛋欣。
缺點(diǎn):
- 對(duì)結(jié)構(gòu)化查詢的支持比較差。
- 數(shù)據(jù)庫(kù)容量受到物理內(nèi)存的限制如贷,不適合用作海量數(shù)據(jù)的高性能讀寫(xiě)豁状,因此Redis適合的場(chǎng)景主要局限在較小數(shù)據(jù)量的操作。
- Redis 較難支持在線擴(kuò)容倒得,在集群容量達(dá)到上限時(shí)在線擴(kuò)容會(huì)變得很復(fù)雜泻红。
Redis為什么這么快?
- 基于內(nèi)存:Redis是使用內(nèi)存存儲(chǔ)霞掺,沒(méi)有磁盤(pán)IO上的開(kāi)銷(xiāo)谊路。數(shù)據(jù)存在內(nèi)存中,讀寫(xiě)速度快菩彬。
- 單線程實(shí)現(xiàn)( Redis 6.0以前):Redis使用單個(gè)線程處理請(qǐng)求缠劝,避免了多個(gè)線程之間線程切換和鎖資源爭(zhēng)用的開(kāi)銷(xiāo)。
- IO多路復(fù)用模型:Redis 采用 IO 多路復(fù)用技術(shù)骗灶。Redis 使用單線程來(lái)輪詢描述符惨恭,將數(shù)據(jù)庫(kù)的操作都轉(zhuǎn)換成了事件,不在網(wǎng)絡(luò)I/O上浪費(fèi)過(guò)多的時(shí)間耙旦。
- 高效的數(shù)據(jù)結(jié)構(gòu):Redis 每種數(shù)據(jù)類(lèi)型底層都做了優(yōu)化脱羡,目的就是為了追求更快的速度。
Redis為何選擇單線程
- 避免過(guò)多的上下文切換開(kāi)銷(xiāo)免都。程序始終運(yùn)行在進(jìn)程中單個(gè)線程內(nèi)锉罐,沒(méi)有多線程切換的場(chǎng)景。
- 避免同步機(jī)制的開(kāi)銷(xiāo):如果 Redis選擇多線程模型绕娘,需要考慮數(shù)據(jù)同步的問(wèn)題脓规,則必然會(huì)引入某些同步機(jī)制,會(huì)導(dǎo)致在操作數(shù)據(jù)過(guò)程中帶來(lái)更多的開(kāi)銷(xiāo)险领,增加程序復(fù)雜度的同時(shí)還會(huì)降低性能侨舆。
- 實(shí)現(xiàn)簡(jiǎn)單,方便維護(hù):如果 Redis使用多線程模式绢陌,那么所有的底層數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)都必須考慮線程安全問(wèn)題挨下,那么 Redis 的實(shí)現(xiàn)將會(huì)變得更加復(fù)雜。
Redis6.0為何引入多線程下面?
Redis支持多線程主要有兩個(gè)原因:
- 可以充分利用服務(wù)器 CPU 資源复颈,單線程模型的主線程只能利用一個(gè)cpu;
- 多線程任務(wù)可以分?jǐn)?Redis 同步 IO 讀寫(xiě)的負(fù)荷。
Redis應(yīng)用場(chǎng)景有哪些耗啦?
- 緩存熱點(diǎn)數(shù)據(jù)凿菩,緩解數(shù)據(jù)庫(kù)的壓力。
- 利用 Redis 原子性的自增操作帜讲,可以實(shí)現(xiàn)計(jì)數(shù)器的功能衅谷,比如統(tǒng)計(jì)用戶點(diǎn)贊數(shù)、用戶訪問(wèn)數(shù)等似将。
- 簡(jiǎn)單的消息隊(duì)列获黔,可以使用Redis自身的發(fā)布/訂閱模式或者List來(lái)實(shí)現(xiàn)簡(jiǎn)單的消息隊(duì)列,實(shí)現(xiàn)異步操作在验。
- 限速器玷氏,可用于限制某個(gè)用戶訪問(wèn)某個(gè)接口的頻率,比如秒殺場(chǎng)景用于防止用戶快速點(diǎn)擊帶來(lái)不必要的壓力腋舌。
- 好友關(guān)系盏触,利用集合的一些命令,比如交集块饺、并集赞辩、差集等,實(shí)現(xiàn)共同好友授艰、共同愛(ài)好之類(lèi)的功能辨嗽。
Memcached和Redis的區(qū)別?
- Redis 只使用單核淮腾,而 Memcached 可以使用多核糟需。
- MemCached 數(shù)據(jù)結(jié)構(gòu)單一,僅用來(lái)緩存數(shù)據(jù)来破,而 Redis 支持多種數(shù)據(jù)類(lèi)型篮灼。
- MemCached 不支持?jǐn)?shù)據(jù)持久化,重啟后數(shù)據(jù)會(huì)消失徘禁。Redis 支持?jǐn)?shù)據(jù)持久化。
- Redis 提供主從同步機(jī)制和 cluster 集群部署能力髓堪,能夠提供高可用服務(wù)送朱。Memcached 沒(méi)有提供原生的集群模式,需要依靠客戶端實(shí)現(xiàn)往集群中分片寫(xiě)入數(shù)據(jù)干旁。
- Redis 的速度比 Memcached 快很多驶沼。
- Redis 使用單線程的多路 IO 復(fù)用模型,Memcached使用多線程的非阻塞 IO 模型争群。
Redis 數(shù)據(jù)類(lèi)型有哪些回怜?
基本數(shù)據(jù)類(lèi)型:
- String:最常用的一種數(shù)據(jù)類(lèi)型,String類(lèi)型的值可以是字符串换薄、數(shù)字或者二進(jìn)制玉雾,但值最大不能超過(guò)512MB翔试。
- Hash:Hash 是一個(gè)鍵值對(duì)集合。
- Set:無(wú)序去重的集合复旬。Set 提供了交集垦缅、并集等方法,對(duì)于實(shí)現(xiàn)共同好友驹碍、共同關(guān)注等功能特別方便壁涎。
- List:有序可重復(fù)的集合,底層是依賴雙向鏈表實(shí)現(xiàn)的志秃。
- SortedSet:有序Set怔球。內(nèi)部維護(hù)了一個(gè)score的參數(shù)來(lái)實(shí)現(xiàn)。適用于排行榜和帶權(quán)重的消息隊(duì)列等場(chǎng)景浮还。
特殊的數(shù)據(jù)類(lèi)型:
- Bitmap:位圖庞溜,可以認(rèn)為是一個(gè)以位為單位數(shù)組,數(shù)組中的每個(gè)單元只能存0或者1碑定,數(shù)組的下標(biāo)在 Bitmap 中叫做偏移量流码。Bitmap的長(zhǎng)度與集合中元素個(gè)數(shù)無(wú)關(guān),而是與基數(shù)的上限有關(guān)延刘。
- Hyperloglog漫试。HyperLogLog 是用來(lái)做基數(shù)統(tǒng)計(jì)的算法,其優(yōu)點(diǎn)是碘赖,在輸入元素的數(shù)量或者體積非常非常大時(shí)驾荣,計(jì)算基數(shù)所需的空間總是固定的、并且是很小的普泡。典型的使用場(chǎng)景是統(tǒng)計(jì)獨(dú)立訪客播掷。
- Geospatial :主要用于存儲(chǔ)地理位置信息,并對(duì)存儲(chǔ)的信息進(jìn)行操作撼班,適用場(chǎng)景如定位歧匈、附近的人等。
keys命令存在的問(wèn)題砰嘁?
redis的單線程的件炉。keys指令會(huì)導(dǎo)致線程阻塞一段時(shí)間,直到執(zhí)行完畢矮湘,服務(wù)才能恢復(fù)斟冕。scan采用漸進(jìn)式遍歷的方式來(lái)解決keys命令可能帶來(lái)的阻塞問(wèn)題,每次scan命令的時(shí)間復(fù)雜度是O(1)缅阳,但是要真正實(shí)現(xiàn)keys的功能磕蛇,需要執(zhí)行多次scan。
scan的缺點(diǎn):在scan的過(guò)程中如果有鍵的變化(增加、刪除秀撇、修改)超棺,遍歷過(guò)程可能會(huì)有以下問(wèn)題:新增的鍵可能沒(méi)有遍歷到,遍歷出了重復(fù)的鍵等情況捌袜,也就是說(shuō)scan并不能保證完整的遍歷出來(lái)所有的鍵说搅。
SortedSet和List異同點(diǎn)?
相同點(diǎn):
- 都是有序的虏等;
- 都可以獲得某個(gè)范圍內(nèi)的元素弄唧。
不同點(diǎn):
- 列表基于鏈表實(shí)現(xiàn),獲取兩端元素速度快霍衫,訪問(wèn)中間元素速度慢候引;
- 有序集合基于散列表和跳躍表實(shí)現(xiàn),訪問(wèn)中間元素時(shí)間復(fù)雜度是OlogN敦跌;
- 列表不能簡(jiǎn)單的調(diào)整某個(gè)元素的位置澄干,有序列表可以(更改元素的分?jǐn)?shù));
- 有序集合更耗內(nèi)存柠傍。
Redis事務(wù)
事務(wù)的原理是將一個(gè)事務(wù)范圍內(nèi)的若干命令發(fā)送給Redis麸俘,然后再讓Redis依次執(zhí)行這些命令。
事務(wù)的生命周期:
- 使用MULTI開(kāi)啟一個(gè)事務(wù)
- 在開(kāi)啟事務(wù)的時(shí)候惧笛,每次操作的命令將會(huì)被插入到一個(gè)隊(duì)列中从媚,同時(shí)這個(gè)命令并不會(huì)被真的執(zhí)行
-
EXEC命令進(jìn)行提交事務(wù)
一個(gè)事務(wù)范圍內(nèi)某個(gè)命令出錯(cuò)不會(huì)影響其他命令的執(zhí)行,不保證原子性:
WATCH命令
WATCH命令可以監(jiān)控一個(gè)或多個(gè)鍵患整,一旦其中有一個(gè)鍵被修改拜效,之后的事務(wù)就不會(huì)執(zhí)行(類(lèi)似于樂(lè)觀鎖)。執(zhí)行EXEC命令之后各谚,就會(huì)自動(dòng)取消監(jiān)控紧憾。
比如上面的代碼中:
- watch name開(kāi)啟了對(duì)name這個(gè)key的監(jiān)控
- 修改name的值
- 開(kāi)啟事務(wù)a
- 在事務(wù)a中設(shè)置了name和gender的值
- 使用EXEC命令進(jìn)提交事務(wù)
- 使用命令get gender發(fā)現(xiàn)不存在,即事務(wù)a沒(méi)有執(zhí)行
使用UNWATCH可以取消WATCH命令對(duì)key的監(jiān)控昌渤,所有監(jiān)控鎖將會(huì)被取消赴穗。
持久化機(jī)制
持久化就是把內(nèi)存的數(shù)據(jù)寫(xiě)到磁盤(pán)中,防止服務(wù)宕機(jī)導(dǎo)致內(nèi)存數(shù)據(jù)丟失愈涩。
Redis支持兩種方式的持久化望抽,一種是RDB的方式,一種是AOF的方式履婉。前者會(huì)根據(jù)指定的規(guī)則定時(shí)將內(nèi)存中的數(shù)據(jù)存儲(chǔ)在硬盤(pán)上,而后者在每次執(zhí)行完命令后將命令記錄下來(lái)斟览。一般將兩者結(jié)合使用毁腿。
RDB方式
RDB是 Redis 默認(rèn)的持久化方案。RDB持久化時(shí)會(huì)將內(nèi)存中的數(shù)據(jù)寫(xiě)入到磁盤(pán)中,在指定目錄下生成一個(gè)dump.rdb文件已烤。Redis 重啟會(huì)加載dump.rdb文件恢復(fù)數(shù)據(jù)鸠窗。
bgsave是主流的觸發(fā) RDB 持久化的方式,執(zhí)行過(guò)程如下:
- 執(zhí)行BGSAVE命令Redis
- 父進(jìn)程判斷當(dāng)前是否存在正在執(zhí)行的子進(jìn)程胯究,如果存在稍计,BGSAVE命令直接返回。
- 父進(jìn)程執(zhí)行fork操作創(chuàng)建子進(jìn)程裕循,fork操作過(guò)程中父進(jìn)程會(huì)阻塞臣嚣。
- 父進(jìn)程fork完成后,父進(jìn)程繼續(xù)接收并處理客戶端的請(qǐng)求剥哑,而子進(jìn)程開(kāi)始將內(nèi)存中的數(shù)據(jù)寫(xiě)進(jìn)硬盤(pán)的臨時(shí)文件硅则;
- 當(dāng)子進(jìn)程寫(xiě)完所有數(shù)據(jù)后會(huì)用該臨時(shí)文件替換舊的 RDB 文件。
Redis啟動(dòng)時(shí)會(huì)讀取RDB快照文件株婴,將數(shù)據(jù)從硬盤(pán)載入內(nèi)存怎虫。通過(guò) RDB 方式的持久化,一旦Redis異常退出困介,就會(huì)丟失最近一次持久化以后更改的數(shù)據(jù)大审。
觸發(fā) RDB 持久化的方式:
- 手動(dòng)觸發(fā):用戶執(zhí)行SAVE或BGSAVE命令。SAVE命令執(zhí)行快照的過(guò)程會(huì)阻塞所有客戶端的請(qǐng)求座哩,應(yīng)避免在生產(chǎn)環(huán)境使用此命令徒扶。BGSAVE命令可以在后臺(tái)異步進(jìn)行快照操作,快照的同時(shí)服務(wù)器還可以繼續(xù)響應(yīng)客戶端的請(qǐng)求八回,因此需要手動(dòng)執(zhí)行快照時(shí)推薦使用BGSAVE命令酷愧。
- 被動(dòng)觸發(fā):
- 根據(jù)配置規(guī)則進(jìn)行自動(dòng)快照,如SAVE 100 10缠诅,100秒內(nèi)至少有10個(gè)鍵被修改則進(jìn)行快照溶浴。如果
- 從節(jié)點(diǎn)執(zhí)行全量復(fù)制操作,主節(jié)點(diǎn)會(huì)自動(dòng)執(zhí)行BGSAVE生成 RDB 文件并發(fā)送給從節(jié)點(diǎn)管引。
- 默認(rèn)情況下執(zhí)行shutdown命令時(shí)士败,如果沒(méi)有開(kāi)啟 AOF 持久化功能則自動(dòng)執(zhí)行·BGSAVE·。
優(yōu)點(diǎn):
Redis 加載 RDB 恢復(fù)數(shù)據(jù)遠(yuǎn)遠(yuǎn)快于 AOF 的方式褥伴。使用單獨(dú)子進(jìn)程來(lái)進(jìn)行持久化谅将,主進(jìn)程不會(huì)進(jìn)行任何 IO 操作,保證了 Redis 的高性能重慢。
缺點(diǎn):
- RDB方式數(shù)據(jù)無(wú)法做到實(shí)時(shí)持久化饥臂。因?yàn)锽GSAVE每次運(yùn)行都要執(zhí)行fork操作創(chuàng)建子進(jìn)程,屬于重量級(jí)操作似踱,頻繁執(zhí)行成本比較高隅熙。
- RDB 文件使用特定二進(jìn)制格式保存稽煤,Redis 版本升級(jí)過(guò)程中有多個(gè)格式的 RDB 版本,存在老版本 Redis 無(wú)法兼容新版 RDB 格式的問(wèn)題囚戚。
AOF方式
AOF(append only file)持久化:以獨(dú)立日志的方式記錄每次寫(xiě)命令酵熙,Redis重啟時(shí)會(huì)重新執(zhí)行AOF文件中的命令達(dá)到恢復(fù)數(shù)據(jù)的目的。AOF的主要作用是解決了數(shù)據(jù)持久化的實(shí)時(shí)性驰坊,AOF 是Redis持久化的主流方式匾二。
默認(rèn)情況下Redis沒(méi)有開(kāi)啟AOF方式的持久化,可以通過(guò)appendonly參數(shù)啟用:appendonly yes拳芙。開(kāi)啟AOF方式持久化后每執(zhí)行一條寫(xiě)命令察藐,Redis就會(huì)將該命令寫(xiě)進(jìn)aof_buf緩沖區(qū),AOF緩沖區(qū)根據(jù)對(duì)應(yīng)的策略向硬盤(pán)做同步操作态鳖。
默認(rèn)情況下系統(tǒng)每30秒會(huì)執(zhí)行一次同步操作转培。為了防止緩沖區(qū)數(shù)據(jù)丟失,可以在Redis寫(xiě)入AOF文件后主動(dòng)要求系統(tǒng)將緩沖區(qū)數(shù)據(jù)同步到硬盤(pán)上浆竭〗耄可以通過(guò)appendfsync參數(shù)設(shè)置同步的時(shí)機(jī)。
appendfsync always //每次寫(xiě)入aof文件都會(huì)執(zhí)行同步邦泄,最安全最慢删窒,不建議配置
appendfsync everysec //既保證性能也保證安全,建議配置
appendfsync no //由操作系統(tǒng)決定何時(shí)進(jìn)行同步操作
接下來(lái)看一下 AOF 持久化執(zhí)行流程:
- 所有的寫(xiě)入命令會(huì)追加到 AOP 緩沖區(qū)中顺囊。
- AOF 緩沖區(qū)根據(jù)對(duì)應(yīng)的策略向硬盤(pán)同步肌索。
- 隨著 AOF 文件越來(lái)越大,需要定期對(duì) AOF 文件進(jìn)行重寫(xiě)特碳,達(dá)到壓縮文件體積的目的诚亚。AOF文件重寫(xiě)是把Redis進(jìn)程內(nèi)的數(shù)據(jù)轉(zhuǎn)化為寫(xiě)命令同步到新AOF文件的過(guò)程。
- 當(dāng) Redis 服務(wù)器重啟時(shí)午乓,可以加載 AOF 文件進(jìn)行數(shù)據(jù)恢復(fù)站宗。
優(yōu)點(diǎn):
- AOF可以更好的保護(hù)數(shù)據(jù)不丟失,可以配置 AOF 每秒執(zhí)行一次fsync操作益愈,如果Redis進(jìn)程掛掉梢灭,最多丟失1秒的數(shù)據(jù)。
- AOF以append-only的模式寫(xiě)入蒸其,所以沒(méi)有磁盤(pán)尋址的開(kāi)銷(xiāo)敏释,寫(xiě)入性能非常高。
缺點(diǎn):
- 對(duì)于同一份文件AOF文件比RDB數(shù)據(jù)快照要大摸袁。
- 數(shù)據(jù)恢復(fù)比較慢钥顽。
RDB和AOF如何選擇?
通常來(lái)說(shuō)靠汁,應(yīng)該同時(shí)使用兩種持久化方案耳鸯,以保證數(shù)據(jù)安全湿蛔。
- 如果數(shù)據(jù)不敏感膀曾,且可以從其他地方重新生成县爬,可以關(guān)閉持久化。
- 如果數(shù)據(jù)比較重要添谊,且能夠承受幾分鐘的數(shù)據(jù)丟失财喳,比如緩存等,只需要使用RDB即可斩狱。
- 如果是用做內(nèi)存數(shù)據(jù)耳高,要使用Redis的持久化,建議是RDB和AOF都開(kāi)啟所踊。
- 如果只用AOF泌枪,優(yōu)先使用everysec的配置選擇,因?yàn)樗诳煽啃院托阅苤g取了一個(gè)平衡秕岛。
當(dāng)RDB與AOF兩種方式都開(kāi)啟時(shí)碌燕,Redis會(huì)優(yōu)先使用AOF恢復(fù)數(shù)據(jù),因?yàn)锳OF保存的文件比RDB文件更完整继薛。
Redis常見(jiàn)的部署方式有哪些修壕?
Redis的幾種常見(jiàn)使用方式包括:
- 單機(jī)版
- Redis主從
- Redis Sentinel(哨兵)
- Redis Cluster
使用場(chǎng)景:
- 單機(jī)版:很少使用。存在的問(wèn)題:1遏考、內(nèi)存容量有限 2慈鸠、處理能力有限 3、無(wú)法高可用灌具。
- 主從模式:master 節(jié)點(diǎn)掛掉后青团,需要手動(dòng)指定新的 master,可用性不高咖楣,基本不用督笆。
- 哨兵模式:master 節(jié)點(diǎn)掛掉后,哨兵進(jìn)程會(huì)主動(dòng)選舉新的 master截歉,可用性高胖腾,但是每個(gè)節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)是一樣的,浪費(fèi)內(nèi)存空間瘪松。數(shù)據(jù)量不是很多咸作,集群規(guī)模不是很大,需要自動(dòng)容錯(cuò)容災(zāi)的時(shí)候使用宵睦。
- Redis cluster:主要是針對(duì)海量數(shù)據(jù)+高并發(fā)+高可用的場(chǎng)景记罚,如果是海量數(shù)據(jù),如果你的數(shù)據(jù)量很大壳嚎,那么建議就用Redis cluster桐智,所有主節(jié)點(diǎn)的容量總和就是Redis cluster可緩存的數(shù)據(jù)容量末早。
主從復(fù)制
Redis的復(fù)制功能是支持多個(gè)數(shù)據(jù)庫(kù)之間的數(shù)據(jù)同步。主數(shù)據(jù)庫(kù)可以進(jìn)行讀寫(xiě)操作说庭,當(dāng)主數(shù)據(jù)庫(kù)的數(shù)據(jù)發(fā)生變化時(shí)會(huì)自動(dòng)將數(shù)據(jù)同步到從數(shù)據(jù)庫(kù)然磷。從數(shù)據(jù)庫(kù)一般是只讀的,它會(huì)接收主數(shù)據(jù)庫(kù)同步過(guò)來(lái)的數(shù)據(jù)刊驴。一個(gè)主數(shù)據(jù)庫(kù)可以有多個(gè)從數(shù)據(jù)庫(kù)姿搜,而一個(gè)從數(shù)據(jù)庫(kù)只能有一個(gè)主數(shù)據(jù)庫(kù)。
redis-server //啟動(dòng)Redis實(shí)例作為主數(shù)據(jù)庫(kù)
redis-server --port 6380 --slaveof 127.0.0.1 6379 //啟動(dòng)另一個(gè)實(shí)例作為從數(shù)據(jù)庫(kù)
slaveof 127.0.0.1 6379
SLAVEOF NO ONE //停止接收其他數(shù)據(jù)庫(kù)的同步并轉(zhuǎn)化為主數(shù)據(jù)庫(kù)捆憎。
主從復(fù)制的原理舅柜?
- 當(dāng)啟動(dòng)一個(gè)從節(jié)點(diǎn)時(shí),它會(huì)發(fā)送一個(gè) PSYNC 命令給主節(jié)點(diǎn)躲惰;
- 如果是從節(jié)點(diǎn)初次連接到主節(jié)點(diǎn)致份,那么會(huì)觸發(fā)一次全量復(fù)制。此時(shí)主節(jié)點(diǎn)會(huì)啟動(dòng)一個(gè)后臺(tái)線程础拨,開(kāi)始生成一份 RDB 快照文件氮块;
- 同時(shí)還會(huì)將從客戶端 client 新收到的所有寫(xiě)命令緩存在內(nèi)存中。RDB 文件生成完畢后太伊, 主節(jié)點(diǎn)會(huì)將RDB文件發(fā)送給從節(jié)點(diǎn)雇锡,從節(jié)點(diǎn)會(huì)先將RDB文件寫(xiě)入本地磁盤(pán),然后再?gòu)谋镜卮疟P(pán)加載到內(nèi)存中僚焦;
- 接著主節(jié)點(diǎn)會(huì)將內(nèi)存中緩存的寫(xiě)命令發(fā)送到從節(jié)點(diǎn)锰提,從節(jié)點(diǎn)同步這些數(shù)據(jù);
- 如果從節(jié)點(diǎn)跟主節(jié)點(diǎn)之間網(wǎng)絡(luò)出現(xiàn)故障芳悲,連接斷開(kāi)了立肘,會(huì)自動(dòng)重連,連接之后主節(jié)點(diǎn)僅會(huì)將部分缺失的數(shù)據(jù)同步給從節(jié)點(diǎn)名扛。
哨兵Sentinel
主從復(fù)制存在不能自動(dòng)故障轉(zhuǎn)移谅年、達(dá)不到高可用的問(wèn)題。哨兵模式解決了這些問(wèn)題肮韧。通過(guò)哨兵機(jī)制可以自動(dòng)切換主從節(jié)點(diǎn)融蹂。
客戶端連接Redis的時(shí)候,先連接哨兵弄企,哨兵會(huì)告訴客戶端Redis主節(jié)點(diǎn)的地址超燃,然后客戶端連接上Redis并進(jìn)行后續(xù)的操作。當(dāng)主節(jié)點(diǎn)宕機(jī)的時(shí)候拘领,哨兵監(jiān)測(cè)到主節(jié)點(diǎn)宕機(jī)意乓,會(huì)重新推選出某個(gè)表現(xiàn)良好的從節(jié)點(diǎn)成為新的主節(jié)點(diǎn),然后通過(guò)發(fā)布訂閱模式通知其他的從服務(wù)器约素,讓它們切換主機(jī)届良。
工作原理
- 每個(gè)Sentinel以每秒鐘一次的頻率向它所知道的Master笆凌,Slave以及其他 Sentinel實(shí)例發(fā)送一個(gè) PING命令。
- 如果一個(gè)實(shí)例距離最后一次有效回復(fù) PING 命令的時(shí)間超過(guò)指定值士葫, 則這個(gè)實(shí)例會(huì)被 Sentine 標(biāo)記為主觀下線乞而。
- 如果一個(gè)Master被標(biāo)記為主觀下線,則正在監(jiān)視這個(gè)Master的所有 Sentinel要以每秒一次的頻率確認(rèn)Master是否真正進(jìn)入主觀下線狀態(tài)为障。
- 當(dāng)有足夠數(shù)量的 Sentinel(大于等于配置文件指定值)在指定的時(shí)間范圍內(nèi)確認(rèn)Master的確進(jìn)入了主觀下線狀態(tài)晦闰, 則Master會(huì)被標(biāo)記為客觀下線 。若沒(méi)有足夠數(shù)量的 Sentinel同意 Master 已經(jīng)下線鳍怨, Master 的客觀下線狀態(tài)就會(huì)被解除。 若 Master重新向 Sentinel 的 PING 命令返回有效回復(fù)跪妥, Master 的主觀下線狀態(tài)就會(huì)被移除鞋喇。
- 哨兵節(jié)點(diǎn)會(huì)選舉出哨兵 leader,負(fù)責(zé)故障轉(zhuǎn)移的工作眉撵。
- 哨兵 leader 會(huì)推選出某個(gè)表現(xiàn)良好的從節(jié)點(diǎn)成為新的主節(jié)點(diǎn)侦香,然后通知其他從節(jié)點(diǎn)更新主節(jié)點(diǎn)信息。
Redis cluster
哨兵模式解決了主從復(fù)制不能自動(dòng)故障轉(zhuǎn)移纽疟、達(dá)不到高可用的問(wèn)題罐韩,但還是存在主節(jié)點(diǎn)的寫(xiě)能力、容量受限于單機(jī)配置的問(wèn)題污朽。而cluster模式實(shí)現(xiàn)了Redis的分布式存儲(chǔ)散吵,每個(gè)節(jié)點(diǎn)存儲(chǔ)不同的內(nèi)容,解決主節(jié)點(diǎn)的寫(xiě)能力蟆肆、容量受限于單機(jī)配置的問(wèn)題矾睦。
Redis cluster集群節(jié)點(diǎn)最小配置6個(gè)節(jié)點(diǎn)以上(3主3從),其中主節(jié)點(diǎn)提供讀寫(xiě)操作炎功,從節(jié)點(diǎn)作為備用節(jié)點(diǎn)枚冗,不提供請(qǐng)求,只作為故障轉(zhuǎn)移使用蛇损。
Redis cluster采用虛擬槽分區(qū)赁温,所有的鍵根據(jù)哈希函數(shù)映射到0~16383個(gè)整數(shù)槽內(nèi),每個(gè)節(jié)點(diǎn)負(fù)責(zé)維護(hù)一部分槽以及槽所映射的鍵值數(shù)據(jù)淤齐。
哈希槽是如何映射到 Redis 實(shí)例上的股囊?
- 對(duì)鍵值對(duì)的key使用 crc16 算法計(jì)算一個(gè)結(jié)果將結(jié)果
- 對(duì) 16384 取余,得到的值表示 key 對(duì)應(yīng)的哈希槽
- 根據(jù)該槽信息定位到對(duì)應(yīng)的實(shí)例
優(yōu)點(diǎn):
- 無(wú)中心架構(gòu)床玻,支持動(dòng)態(tài)擴(kuò)容毁涉;
- 數(shù)據(jù)按照slot存儲(chǔ)分布在多個(gè)節(jié)點(diǎn),節(jié)點(diǎn)間數(shù)據(jù)共享锈死,可動(dòng)態(tài)調(diào)整數(shù)據(jù)分布贫堰;
- 高可用性穆壕。部分節(jié)點(diǎn)不可用時(shí),集群仍可用其屏。集群模式能夠?qū)崿F(xiàn)自動(dòng)故障轉(zhuǎn)移(failover)喇勋,節(jié)點(diǎn)之間通過(guò)gossip協(xié)議交換狀態(tài)信息,用投票機(jī)制完成Slave到Master的角色轉(zhuǎn)換偎行。
缺點(diǎn):
- 不支持批量操作(pipeline)川背。
- 數(shù)據(jù)通過(guò)異步復(fù)制,不保證數(shù)據(jù)的強(qiáng)一致性蛤袒。
- 事務(wù)操作支持有限熄云,只支持多key在同一節(jié)點(diǎn)上的事務(wù)操作,當(dāng)多個(gè)key分布于不同的節(jié)點(diǎn)上時(shí)無(wú)法使用事務(wù)功能妙真。
- key作為數(shù)據(jù)分區(qū)的最小粒度缴允,不能將一個(gè)很大的鍵值對(duì)象如hash、list等映射到不同的節(jié)點(diǎn)
- 不支持多數(shù)據(jù)庫(kù)空間珍德,單機(jī)下的Redis可以支持到16個(gè)數(shù)據(jù)庫(kù)练般,集群模式下只能使用1個(gè)數(shù)據(jù)庫(kù)空間。
哈希分區(qū)算法有哪些锈候?
節(jié)點(diǎn)取余分區(qū)
使用特定的數(shù)據(jù)薄料,如Redis的鍵或用戶ID,對(duì)節(jié)點(diǎn)數(shù)量N取余:hash(key)%N計(jì)算出哈希值泵琳,用來(lái)決定數(shù)據(jù)映射到哪一個(gè)節(jié)點(diǎn)上摄职。優(yōu)點(diǎn)是簡(jiǎn)單性。擴(kuò)容時(shí)通常采用翻倍擴(kuò)容虑稼,避免數(shù)據(jù)映射全部被打亂導(dǎo)致全量遷移的情況琳钉。
一致性哈希分區(qū)
為系統(tǒng)中每個(gè)節(jié)點(diǎn)分配一個(gè)token,范圍一般在0~232蛛倦,這些token構(gòu)成一個(gè)哈希環(huán)歌懒。數(shù)據(jù)讀寫(xiě)執(zhí)行節(jié)點(diǎn)查找操作時(shí),先根據(jù)key計(jì)算hash值溯壶,然后順時(shí)針找到第一個(gè)大于等于該哈希值的token節(jié)點(diǎn)及皂。這種方式相比節(jié)點(diǎn)取余最大的好處在于加入和刪除節(jié)點(diǎn)只影響哈希環(huán)中相鄰的節(jié)點(diǎn),對(duì)其他節(jié)點(diǎn)無(wú)影響且改。
虛擬槽分區(qū)
所有的鍵根據(jù)哈希函數(shù)映射到0~16383整數(shù)槽內(nèi)验烧,計(jì)算公式:slot=CRC16(key)&16383。每一個(gè)節(jié)點(diǎn)負(fù)責(zé)維護(hù)一部分槽以及槽所映射的鍵值數(shù)據(jù)又跛。Redis Cluser采用虛擬槽分區(qū)算法碍拆。
過(guò)期鍵的刪除策略?
- 被動(dòng)刪除。在訪問(wèn)key時(shí)感混,如果發(fā)現(xiàn)key已經(jīng)過(guò)期端幼,那么會(huì)將key刪除冠跷。
- 主動(dòng)刪除函似。定時(shí)清理key,每次清理會(huì)依次遍歷所有DB魏割,從db隨機(jī)取出20個(gè)key庭呜,如果過(guò)期就刪除滑进,如果其中有5個(gè)key過(guò)期,那么就繼續(xù)對(duì)這個(gè)db進(jìn)行清理募谎,否則開(kāi)始清理下一個(gè)db扶关。
- 內(nèi)存不夠時(shí)清理。Redis有最大內(nèi)存的限制近哟,通過(guò)maxmemory參數(shù)可以設(shè)置最大內(nèi)存驮审,當(dāng)使用的內(nèi)存超過(guò)了設(shè)置的最大內(nèi)存,就要進(jìn)行內(nèi)存釋放吉执, 在進(jìn)行內(nèi)存釋放的時(shí)候,會(huì)按照配置的淘汰策略清理內(nèi)存地来。
內(nèi)存淘汰策略有哪些戳玫?
當(dāng)Redis的內(nèi)存超過(guò)最大允許的內(nèi)存之后,Redis 會(huì)觸發(fā)內(nèi)存淘汰策略未斑,刪除一些不常用的數(shù)據(jù)咕宿,以保證Redis服務(wù)器正常運(yùn)行。
Redis4.0前提供 6 種數(shù)據(jù)淘汰策略:
- volatile-lru:LRU(Least Recently Used)蜡秽,最近使用府阀。利用LRU算法移除設(shè)置了過(guò)期時(shí)間的key
- allkeys-lru:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),從數(shù)據(jù)集中移除最近最少使用的key
- volatile-ttl:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集中挑選將要過(guò)期的數(shù)據(jù)淘汰
- volatile-random:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰
- allkeys-random:從數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰
- no-eviction:禁止刪除數(shù)據(jù)芽突,當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)试浙,新寫(xiě)入操作會(huì)報(bào)錯(cuò)
Redis4.0后增加以下兩種:
- volatile-lfu:LFU,Least Frequently Used寞蚌,最少使用田巴,從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集中挑選最不經(jīng)常使用的數(shù)據(jù)淘汰。
- allkeys-lfu:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí)挟秤,從數(shù)據(jù)集中移除最不經(jīng)常使用的key壹哺。
內(nèi)存淘汰策略可以通過(guò)配置文件來(lái)修改,相應(yīng)的配置項(xiàng)是maxmemory-policy艘刚,默認(rèn)配置是noeviction管宵。
如何保證緩存與數(shù)據(jù)庫(kù)雙寫(xiě)時(shí)的數(shù)據(jù)一致性?
先刪除緩存再更新數(shù)據(jù)庫(kù)進(jìn)行更新操作時(shí),先刪除緩存箩朴,然后更新數(shù)據(jù)庫(kù)岗喉,后續(xù)的請(qǐng)求再次讀取時(shí),會(huì)從數(shù)據(jù)庫(kù)讀取后再將新數(shù)據(jù)更新到緩存隧饼。
存在的問(wèn)題:刪除緩存數(shù)據(jù)之后沈堡,更新數(shù)據(jù)庫(kù)完成之前,這個(gè)時(shí)間段內(nèi)如果有新的讀請(qǐng)求過(guò)來(lái)燕雁,就會(huì)從數(shù)據(jù)庫(kù)讀取舊數(shù)據(jù)重新寫(xiě)到緩存中诞丽,再次造成不一致,并且后續(xù)讀的都是舊數(shù)據(jù)拐格。先更新數(shù)據(jù)庫(kù)再刪除緩存進(jìn)行更新操作時(shí)僧免,先更新MySQL,成功之后捏浊,刪除緩存懂衩,后續(xù)讀取請(qǐng)求時(shí)再將新數(shù)據(jù)回寫(xiě)緩存。
存在的問(wèn)題:更新MySQL和刪除緩存這段時(shí)間內(nèi)金踪,請(qǐng)求讀取的還是緩存的舊數(shù)據(jù)浊洞,不過(guò)等數(shù)據(jù)庫(kù)更新完成,就會(huì)恢復(fù)一致胡岔,影響相對(duì)比較小法希。異步更新緩存數(shù)據(jù)庫(kù)的更新操作完成后不直接操作緩存,而是把這個(gè)操作命令封裝成消息扔到消息隊(duì)列中靶瘸,然后由Redis自己去消費(fèi)更新數(shù)據(jù)苫亦,消息隊(duì)列可以保證數(shù)據(jù)操作順序一致性,確保緩存系統(tǒng)的數(shù)據(jù)正常怨咪。
緩存穿透
緩存穿透是指查詢一個(gè)不存在的數(shù)據(jù)屋剑,由于緩存是不命中時(shí)被動(dòng)寫(xiě)的,如果從DB查不到數(shù)據(jù)則不寫(xiě)入緩存诗眨,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請(qǐng)求都要到DB去查詢唉匾,失去了緩存的意義。在流量大時(shí)辽话,可能DB就掛掉了肄鸽。
- 緩存空值,不會(huì)查數(shù)據(jù)庫(kù)油啤。
- 采用布隆過(guò)濾器典徘,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中,查詢不存在的數(shù)據(jù)會(huì)被這個(gè)bitmap攔截掉益咬,從而避免了對(duì)DB的查詢壓力逮诲。
布隆過(guò)濾器的原理:當(dāng)一個(gè)元素被加入集合時(shí)帜平,通過(guò)K個(gè)散列函數(shù)將這個(gè)元素映射成一個(gè)位數(shù)組中的K個(gè)點(diǎn),把它們置為1梅鹦。查詢時(shí)裆甩,將元素通過(guò)散列函數(shù)映射之后會(huì)得到k個(gè)點(diǎn),如果這些點(diǎn)有任何一個(gè)0齐唆,則被檢元素一定不在嗤栓,直接返回;如果都是1箍邮,則查詢?cè)睾芸赡艽嬖谲运В蜁?huì)去查詢Redis和數(shù)據(jù)庫(kù)。
緩存雪崩
緩存雪崩是指在我們?cè)O(shè)置緩存時(shí)采用了相同的過(guò)期時(shí)間锭弊,導(dǎo)致緩存在某一時(shí)刻同時(shí)失效堪澎,請(qǐng)求全部轉(zhuǎn)發(fā)到DB,DB瞬時(shí)壓力過(guò)重掛掉味滞。
解決方法:在原有的失效時(shí)間基礎(chǔ)上增加一個(gè)隨機(jī)值樱蛤,使得過(guò)期時(shí)間分散一些。
緩存擊穿
緩存擊穿:大量的請(qǐng)求同時(shí)查詢一個(gè) key 時(shí)剑鞍,此時(shí)這個(gè) key 正好失效了昨凡,就會(huì)導(dǎo)致大量的請(qǐng)求都落到數(shù)據(jù)庫(kù)。緩存擊穿是查詢緩存中失效的 key蚁署,而緩存穿透是查詢不存在的 key土匀。
解決方法:加分布式鎖,第一個(gè)請(qǐng)求的線程可以拿到鎖形用,拿到鎖的線程查詢到了數(shù)據(jù)之后設(shè)置緩存,其他的線程獲取鎖失敗會(huì)等待50ms然后重新到緩存取數(shù)據(jù)证杭,這樣便可以避免大量的請(qǐng)求落到數(shù)據(jù)庫(kù)田度。
public String get(String key) {
String value = redis.get(key);
if (value == null) { //緩存值過(guò)期
String unique_key = systemId + ":" + key;
//設(shè)置30s的超時(shí)
if (redis.set(unique_key, 1, 'NX', 'PX', 30000) == 1) { //設(shè)置成功
value = db.get(key);
redis.set(key, value, expire_secs);
redis.del(unique_key);
} else { //其他線程已經(jīng)到數(shù)據(jù)庫(kù)取值并回寫(xiě)到緩存了,可以重試獲取緩存值
sleep(50);
get(key); //重試
}
} else {
return value;
}
}
Redis 怎么實(shí)現(xiàn)消息隊(duì)列解愤?
使用一個(gè)列表镇饺,讓生產(chǎn)者將任務(wù)使用LPUSH命令放進(jìn)列表,消費(fèi)者不斷用RPOP從列表取出任務(wù)送讲。
BRPOP和RPOP命令相似奸笤,唯一的區(qū)別就是當(dāng)列表沒(méi)有元素時(shí)BRPOP命令會(huì)一直阻塞連接,直到有新元素加入哼鬓。
BRPOP queue 0 //0表示不限制等待時(shí)間
優(yōu)先級(jí)隊(duì)列如果多個(gè)鍵都有元素监右,則按照從左到右的順序取元素。
BLPOP queue:1 queue:2 queue:3 0
發(fā)布/訂閱模式
PSUBSCRIBE channel?* 按照規(guī)則訂閱异希。
PUNSUBSCRIBE channel?*
退訂通過(guò)PSUBSCRIBE命令按照某種規(guī)則訂閱的頻道健盒。其中訂閱規(guī)則要進(jìn)行嚴(yán)格的字符串匹配,PUNSUBSCRIBE* 無(wú)法退訂channel?*規(guī)則。
PUBLISH channel1 hi
SUBSCRIBE channel1
UNSUBSCRIBE channel1 //退訂通過(guò)SUBSCRIBE命令訂閱的頻道扣癣。
缺點(diǎn):在消費(fèi)者下線的情況下惰帽,生產(chǎn)的消息會(huì)丟失。
延時(shí)隊(duì)列
使用sortedset父虑,拿時(shí)間戳作為score该酗,消息內(nèi)容作為key,調(diào)用zadd來(lái)生產(chǎn)消息士嚎,消費(fèi)者用zrangebyscore指令獲取N秒之前的數(shù)據(jù)輪詢進(jìn)行處理呜魄。
pipeline的作用?
redis客戶端執(zhí)行一條命令分4個(gè)過(guò)程: 發(fā)送命令航邢、命令排隊(duì)耕赘、命令執(zhí)行、返回結(jié)果膳殷。使用pipeline可以批量請(qǐng)求操骡,批量返回結(jié)果,執(zhí)行速度比逐條執(zhí)行要快赚窃。
使用pipeline組裝的命令個(gè)數(shù)不能太多册招,不然數(shù)據(jù)量過(guò)大,增加客戶端的等待時(shí)間勒极,還可能造成網(wǎng)絡(luò)阻塞是掰,可以將大量命令的拆分多個(gè)小的pipeline命令完成。
原生批命令(mset和mget)與pipeline對(duì)比:
- 原生批命令是原子性辱匿,pipeline是非原子性键痛。pipeline命令中途異常退出,之前執(zhí)行成功的命令不會(huì)回滾匾七。
- 原生批命令只有一個(gè)命令絮短,但pipeline支持多命令。
LUA腳本
Redis 通過(guò) LUA 腳本創(chuàng)建具有原子性的命令: 當(dāng)lua腳本命令正在運(yùn)行的時(shí)候昨忆,不會(huì)有其他腳本或 Redis 命令被執(zhí)行丁频,實(shí)現(xiàn)組合命令的原子操作。
在Redis中執(zhí)行Lua腳本有兩種方法:eval和evalsha邑贴。eval命令使用內(nèi)置的 Lua 解釋器席里,對(duì) Lua 腳本進(jìn)行求值。
//第一個(gè)參數(shù)是lua腳本拢驾,第二個(gè)參數(shù)是鍵名參數(shù)個(gè)數(shù)奖磁,剩下的是鍵名參數(shù)和附加參數(shù)> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"
lua腳本作用
- Lua腳本在Redis中是原子執(zhí)行的,執(zhí)行過(guò)程中間不會(huì)插入其他命令独旷。
- Lua腳本可以將多條命令一次性打包署穗,有效地減少網(wǎng)絡(luò)開(kāi)銷(xiāo)寥裂。
應(yīng)用場(chǎng)景
舉例:限制接口訪問(wèn)頻率。
在Redis維護(hù)一個(gè)接口訪問(wèn)次數(shù)的鍵值對(duì)案疲,key是接口名稱封恰,value是訪問(wèn)次數(shù)。每次訪問(wèn)接口時(shí)褐啡,會(huì)執(zhí)行以下操作:
- 通過(guò)aop攔截接口的請(qǐng)求诺舔,對(duì)接口請(qǐng)求進(jìn)行計(jì)數(shù),每次進(jìn)來(lái)一個(gè)請(qǐng)求备畦,相應(yīng)的接口訪問(wèn)次數(shù)count加1低飒,存入redis。
- 如果是第一次請(qǐng)求懂盐,則會(huì)設(shè)置count=1褥赊,并設(shè)置過(guò)期時(shí)間。因?yàn)檫@里set()和expire()組合操作不是原子操作莉恼,所以引入lua腳本拌喉,實(shí)現(xiàn)原子操作,避免并發(fā)訪問(wèn)問(wèn)題俐银。
- 如果給定時(shí)間范圍內(nèi)超過(guò)最大訪問(wèn)次數(shù)尿背,則會(huì)拋出異常。
private String buildLuaScript() {
return "local c" +
"\nc = redis.call('get',KEYS[1])" +
"\nif c and tonumber(c) > tonumber(ARGV[1]) then" +
"\nreturn c;" +
"\nend" +
"\nc = redis.call('incr',KEYS[1])" +
"\nif tonumber(c) == 1 then" +
"\nredis.call('expire',KEYS[1],ARGV[2])" +
"\nend" +
"\nreturn c;";}
String luaScript = buildLuaScript();RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class);
Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
PS:這種接口限流的實(shí)現(xiàn)方式比較簡(jiǎn)單捶惜,問(wèn)題也比較多田藐,一般不會(huì)使用,接口限流用的比較多的是令牌桶算法和漏桶算法吱七。
什么是RedLock汽久?
Redis 官方站提出了一種權(quán)威的基于 Redis 實(shí)現(xiàn)分布式鎖的方式名叫 Redlock,此種方式比原先的單節(jié)點(diǎn)的方法更安全踊餐。它可以保證以下特性:
- 安全特性:互斥訪問(wèn)回窘,即永遠(yuǎn)只有一個(gè) client 能拿到鎖
- 避免死鎖:最終 client 都可能拿到鎖,不會(huì)出現(xiàn)死鎖的情況市袖,即使原本鎖住某資源的client 掛掉了
- 容錯(cuò)性:只要大部分 Redis 節(jié)點(diǎn)存活就可以正常提供服務(wù)