Java后端面試高頻問(wèn)題:Redis

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ù)的生命周期:

  1. 使用MULTI開(kāi)啟一個(gè)事務(wù)
  2. 在開(kāi)啟事務(wù)的時(shí)候惧笛,每次操作的命令將會(huì)被插入到一個(gè)隊(duì)列中从媚,同時(shí)這個(gè)命令并不會(huì)被真的執(zhí)行
  3. 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)控紧憾。


比如上面的代碼中:

  1. watch name開(kāi)啟了對(duì)name這個(gè)key的監(jiān)控
  2. 修改name的值
  3. 開(kāi)啟事務(wù)a
  4. 在事務(wù)a中設(shè)置了name和gender的值
  5. 使用EXEC命令進(jìn)提交事務(wù)
  6. 使用命令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ò)程如下:


  1. 執(zhí)行BGSAVE命令Redis
  2. 父進(jìn)程判斷當(dāng)前是否存在正在執(zhí)行的子進(jìn)程胯究,如果存在稍计,BGSAVE命令直接返回。
  3. 父進(jìn)程執(zhí)行fork操作創(chuàng)建子進(jìn)程裕循,fork操作過(guò)程中父進(jìn)程會(huì)阻塞臣嚣。
  4. 父進(jìn)程fork完成后,父進(jìn)程繼續(xù)接收并處理客戶端的請(qǐng)求剥哑,而子進(jìn)程開(kāi)始將內(nèi)存中的數(shù)據(jù)寫(xiě)進(jìn)硬盤(pán)的臨時(shí)文件硅则;
  5. 當(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 持久化的方式:

  1. 手動(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命令酷愧。
  2. 被動(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í)行流程:


  1. 所有的寫(xiě)入命令會(huì)追加到 AOP 緩沖區(qū)中顺囊。
  2. AOF 緩沖區(qū)根據(jù)對(duì)應(yīng)的策略向硬盤(pán)同步肌索。
  3. 隨著 AOF 文件越來(lái)越大,需要定期對(duì) AOF 文件進(jìn)行重寫(xiě)特碳,達(dá)到壓縮文件體積的目的诚亚。AOF文件重寫(xiě)是把Redis進(jìn)程內(nèi)的數(shù)據(jù)轉(zhuǎn)化為寫(xiě)命令同步到新AOF文件的過(guò)程。
  4. 當(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ù)制的原理舅柜?

  1. 當(dāng)啟動(dòng)一個(gè)從節(jié)點(diǎn)時(shí),它會(huì)發(fā)送一個(gè) PSYNC 命令給主節(jié)點(diǎn)躲惰;
  2. 如果是從節(jié)點(diǎn)初次連接到主節(jié)點(diǎn)致份,那么會(huì)觸發(fā)一次全量復(fù)制。此時(shí)主節(jié)點(diǎn)會(huì)啟動(dòng)一個(gè)后臺(tái)線程础拨,開(kāi)始生成一份 RDB 快照文件氮块;
  3. 同時(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)存中僚焦;
  4. 接著主節(jié)點(diǎn)會(huì)將內(nèi)存中緩存的寫(xiě)命令發(fā)送到從節(jié)點(diǎn)锰提,從節(jié)點(diǎn)同步這些數(shù)據(jù);
  5. 如果從節(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ī)届良。


工作原理

  1. 每個(gè)Sentinel以每秒鐘一次的頻率向它所知道的Master笆凌,Slave以及其他 Sentinel實(shí)例發(fā)送一個(gè) PING命令。
  2. 如果一個(gè)實(shí)例距離最后一次有效回復(fù) PING 命令的時(shí)間超過(guò)指定值士葫, 則這個(gè)實(shí)例會(huì)被 Sentine 標(biāo)記為主觀下線乞而。
  3. 如果一個(gè)Master被標(biāo)記為主觀下線,則正在監(jiān)視這個(gè)Master的所有 Sentinel要以每秒一次的頻率確認(rèn)Master是否真正進(jìn)入主觀下線狀態(tài)为障。
  4. 當(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ì)被移除鞋喇。
  5. 哨兵節(jié)點(diǎn)會(huì)選舉出哨兵 leader,負(fù)責(zé)故障轉(zhuǎn)移的工作眉撵。
  6. 哨兵 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í)例上的股囊?

  1. 對(duì)鍵值對(duì)的key使用 crc16 算法計(jì)算一個(gè)結(jié)果將結(jié)果
  2. 對(duì) 16384 取余,得到的值表示 key 對(duì)應(yīng)的哈希槽
  3. 根據(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ù)一致性?

  1. 先刪除緩存再更新數(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ù)拐格。

  2. 先更新數(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ì)比較小法希。

  3. 異步更新緩存數(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就掛掉了肄鸽。

  1. 緩存空值,不會(huì)查數(shù)據(jù)庫(kù)油啤。
  2. 采用布隆過(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í)行以下操作:

  1. 通過(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。
  2. 如果是第一次請(qǐng)求懂盐,則會(huì)設(shè)置count=1褥赊,并設(shè)置過(guò)期時(shí)間。因?yàn)檫@里set()和expire()組合操作不是原子操作莉恼,所以引入lua腳本拌喉,實(shí)現(xiàn)原子操作,避免并發(fā)訪問(wèn)問(wèn)題俐银。
  3. 如果給定時(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ù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市烁涌,隨后出現(xiàn)的幾起案子苍碟,更是在濱河造成了極大的恐慌,老刑警劉巖撮执,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件微峰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡抒钱,警方通過(guò)查閱死者的電腦和手機(jī)蜓肆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)颜凯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人仗扬,你說(shuō)我怎么就攤上這事症概。” “怎么了早芭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵彼城,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我退个,道長(zhǎng)募壕,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任语盈,我火速辦了婚禮舱馅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刀荒。我一直安慰自己代嗤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布照棋。 她就那樣靜靜地躺著资溃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烈炭。 梳的紋絲不亂的頭發(fā)上溶锭,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音符隙,去河邊找鬼趴捅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霹疫,可吹牛的內(nèi)容都是我干的拱绑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼丽蝎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼猎拨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起屠阻,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤红省,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后国觉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吧恃,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年麻诀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了痕寓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傲醉。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖呻率,靈堂內(nèi)的尸體忽然破棺而出硬毕,到底是詐尸還是另有隱情,我是刑警寧澤筷凤,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布昭殉,位于F島的核電站,受9級(jí)特大地震影響藐守,放射性物質(zhì)發(fā)生泄漏挪丢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一卢厂、第九天 我趴在偏房一處隱蔽的房頂上張望乾蓬。 院中可真熱鬧,春花似錦慎恒、人聲如沸任内。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)死嗦。三九已至,卻和暖如春粒氧,著一層夾襖步出監(jiān)牢的瞬間越除,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工外盯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摘盆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓饱苟,卻偏偏與公主長(zhǎng)得像孩擂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子箱熬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容