Redis 面試題
前面已經(jīng)系統(tǒng)的梳理了Redis的各個(gè)功能和搭建的方法闻察,下面我們就來系統(tǒng)的梳理下械荷,關(guān)于Redis在系統(tǒng)中可能會(huì)出現(xiàn)的面試題
-
介紹Redis的集中架構(gòu)模式
- 單機(jī)型
這個(gè)模型很簡單磅甩,多個(gè)客戶端直接連接Redis服務(wù)器
特點(diǎn):內(nèi)存容量有限,支持的QPS有限痴昧,無法擴(kuò)容鸯隅,并且沒有高可用- 主從復(fù)制(讀寫分離)
通過Redis的replication的功能,創(chuàng)建多個(gè)Master服務(wù)器從屬的Slave服務(wù)器送矩,其中Master服務(wù)器進(jìn)行寫操作蚕甥,所有的Slave服務(wù)器進(jìn)行讀操作,這樣只要網(wǎng)絡(luò)正常的話栋荸,Master和Slave都具有相同的數(shù)據(jù)
特點(diǎn):支持了讀QPS的擴(kuò)容菇怀,但是內(nèi)存容量的問題沒有解決,也沒有解決寫QPS的高并發(fā)問題晌块,同時(shí)也沒有高可用- 哨兵
利用Redis的sentinel分布式集群爱沟,來兼容Redis主從服務(wù)器,當(dāng)Master服務(wù)器下線或者不再對(duì)外提供服務(wù)時(shí)匆背,將Slave節(jié)點(diǎn)升級(jí)為Master節(jié)點(diǎn)呼伸,以保證Redis服務(wù)能繼續(xù)對(duì)外提供服務(wù)
特點(diǎn):集群監(jiān)控、消息通知钝尸、故障轉(zhuǎn)移和配置中心括享,解決了上面兩個(gè)架構(gòu)模式中的高可用的問題搂根,但是主從切換需要時(shí)間,可能會(huì)造成數(shù)據(jù)部分丟失- 集群
Redis 3.x版本之后铃辖,提供RedisCluster來創(chuàng)建Redis集群環(huán)境剩愧,利用RedisCluster來管理多個(gè)Redis的服務(wù)
特點(diǎn):無中心架構(gòu)、數(shù)據(jù)按照hashslot存儲(chǔ)分布在多個(gè)節(jié)點(diǎn)澳叉,節(jié)點(diǎn)之間數(shù)據(jù)共享隙咸、可橫向和縱向擴(kuò)容,Master節(jié)點(diǎn)擴(kuò)容成洗,高可用并且能自動(dòng)實(shí)現(xiàn)故障轉(zhuǎn)移五督、節(jié)點(diǎn)之間通過gossip協(xié)議進(jìn)行狀態(tài)信息交換 Redis集群對(duì)于存儲(chǔ)節(jié)點(diǎn)采用的算法是什么?能否詳細(xì)介紹該算法?
Redis在分布式的算法中采用了哈希槽的概念瓶殃,在詳細(xì)介紹哈希槽之前充包,我們需要先簡單的了解下一致性hash算法的概念
- 一致性hash算法
一致性hash算法的總結(jié)參考了博文《一致性哈希算法原理》,現(xiàn)整理如下:
1. 場景:如果一個(gè)集群接收多個(gè)請(qǐng)求遥椿,那么該怎么通過算法將每個(gè)請(qǐng)求分布到集群中對(duì)應(yīng)的服務(wù)基矮,并且滿足高效率呢?
2. 一致性hash算法的原理:將集群中所有的服務(wù)器的節(jié)點(diǎn)先計(jì)算hash值冠场,然后將該值存放管道0~2的32次方的圓形節(jié)點(diǎn)中家浇;
發(fā)送過來的請(qǐng)求也計(jì)算對(duì)應(yīng)的hash值,然后根據(jù)hash值到圓形節(jié)點(diǎn)中順時(shí)針查找最新的服務(wù)節(jié)點(diǎn)碴裙,然后將請(qǐng)求發(fā)送過去钢悲,等待該節(jié)點(diǎn)服務(wù)器的響應(yīng);
3. 如果對(duì)集群進(jìn)行擴(kuò)容舔株,新增一臺(tái)服務(wù)莺琳,則相當(dāng)于在圓形節(jié)點(diǎn)上新增一個(gè)節(jié)點(diǎn),
這樣當(dāng)訪問的請(qǐng)求進(jìn)行hash計(jì)算后的值到圓形節(jié)點(diǎn)上進(jìn)行匹配時(shí)载慈,最多影響該節(jié)點(diǎn)相鄰的節(jié)點(diǎn)惭等,對(duì)其他的節(jié)點(diǎn)沒有任何影響;
4. 一致性hash性質(zhì):平衡性办铡,單調(diào)性辞做,分散性,負(fù)載和平滑性寡具;
- hashslot
hashslot的算法參考了博文《Redis哈希槽》秤茅,先整理如下:
1. RedisCluster采用無中心結(jié)構(gòu),每個(gè)節(jié)點(diǎn)保存數(shù)據(jù)和整個(gè)集群狀態(tài)晒杈,每個(gè)節(jié)點(diǎn)和其他節(jié)點(diǎn)進(jìn)行連接
2. 所有的redis節(jié)點(diǎn)彼此互聯(lián)(PING-PONG機(jī)制),內(nèi)部使用RESP協(xié)議進(jìn)行通訊孔厉,該協(xié)議具有實(shí)現(xiàn)簡單拯钻、快速解析和可讀性好的優(yōu)點(diǎn)帖努;
3. 節(jié)點(diǎn)的fail是通過集群中超過半數(shù)的節(jié)點(diǎn)檢測(cè)失效時(shí)才生效
4. redis-cluster把所有的物理節(jié)點(diǎn)映射到0-16383個(gè)slot上,cluster負(fù)責(zé)維護(hù)node-slot-vlaue
5. Redis集群預(yù)先分好16384個(gè)slot粪般,當(dāng)需要在Redis集群中放置一個(gè)key-value時(shí)拼余,根據(jù)CRC16 mod 15384的值,決定將一個(gè)key放置到哪個(gè)slot中
- 什么是緩存穿透亩歹,緩存擊穿匙监,如果避免,什么是緩存雪崩小作,如何避免
- 緩存穿透
一般前端傳來請(qǐng)求亭姥,先查詢緩存,緩存中沒有了在查詢數(shù)據(jù)庫顾稀,而緩存穿透达罗,前端大量請(qǐng)求過來,查詢緩存中不存在静秆,則再查詢數(shù)據(jù)庫粮揉,而數(shù)據(jù)庫中也不存在,則這個(gè)值無法形成緩存抚笔,那么這個(gè)請(qǐng)求每次都會(huì)請(qǐng)求數(shù)據(jù)庫扶认,這對(duì)數(shù)據(jù)庫就造成了極大的壓力;
我們可以對(duì)空也進(jìn)行緩存殊橙,緩存的失效時(shí)間可以設(shè)置短點(diǎn)辐宾;也可以對(duì)一定不存在的key進(jìn)行過濾,可以將所有可能存在的key存放在一個(gè)大的bitmap中蛀柴,查詢時(shí)通過bitmap進(jìn)行過濾螃概;
- 緩存擊穿
是指一個(gè)Key非常熱點(diǎn),再不停的抗住高并發(fā)鸽疾,大并發(fā)集中對(duì)這個(gè)key進(jìn)行訪問吊洼,如果該key失效了,則持續(xù)的高并發(fā)就會(huì)擊穿緩存制肮,直接請(qǐng)求數(shù)據(jù)庫冒窍,嚴(yán)重時(shí)可能造成數(shù)據(jù)庫宕機(jī)
其實(shí)對(duì)于熱點(diǎn)key來說,很容易解決豺鼻,只要將這個(gè)key對(duì)應(yīng)的失效時(shí)間設(shè)置為永不失效即可综液,當(dāng)然這個(gè)主要是根據(jù)業(yè)務(wù)的需求,一般大key是一段時(shí)間內(nèi)的訪問量是很恐怖的儒飒,但是過了這個(gè)時(shí)間段訪問請(qǐng)求就下來了谬莹,到時(shí)再更改失效時(shí)間即可;
- 緩存雪崩
緩存雪崩是指在某個(gè)時(shí)間段內(nèi),緩存集中過期失效附帽。這樣請(qǐng)求都會(huì)落在數(shù)據(jù)庫上埠戳,對(duì)數(shù)據(jù)庫造成極大的壓力,出現(xiàn)系統(tǒng)崩潰蕉扮;
1. 我們可以將系統(tǒng)中不同種類的key分別設(shè)置不同的失效時(shí)間整胃,
比如說我們可以在原來的過期時(shí)間基礎(chǔ)上增加一個(gè)隨機(jī)值,這樣的話大部分的key的過期時(shí)間就會(huì)有差別喳钟,不會(huì)集中失效<br/>
2. 其次使用緩存降級(jí)屁使,利用eehcache等本地緩存,但主要還是對(duì)源服務(wù)訪問進(jìn)行限流奔则、資源隔離蛮寂、降級(jí)等。
當(dāng)訪問量劇增应狱、服務(wù)出現(xiàn)問題仍然需要保證服務(wù)還是可用的共郭。
系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進(jìn)行自動(dòng)降級(jí),也可以配置開關(guān)實(shí)現(xiàn)人工降級(jí)疾呻,這里會(huì)涉及到運(yùn)維的配合
3. Redis緩存的備份和預(yù)熱
- 緩存并發(fā)
是指多個(gè)redis的client同時(shí)set
解決的思路可以將redis的set操作放到隊(duì)列中使其進(jìn)行串行執(zhí)行
- Redis有哪些常見的用途
- 會(huì)話緩存
- 全頁緩存
- 隊(duì)列
- 排行榜/計(jì)數(shù)器
- 發(fā)布/訂閱
- Redis中事務(wù)相關(guān)的命令有哪些除嘹?
- MULTI
- EXEC
- DISCARD
- WATCH
- Redis如何做內(nèi)存優(yōu)化
在選擇數(shù)據(jù)結(jié)構(gòu)時(shí),盡可能使用散列表(hashes),因?yàn)樯⒘斜硎褂玫膬?nèi)存是非常小的岸蜗,所以你盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表中
- Redis內(nèi)存回收機(jī)制以及過期策略
Redis的內(nèi)存監(jiān)控是使用:redis-cli 中的info
命令來查看的
# Memory
used_memory:26355360#當(dāng)前Redis所有key-value值及內(nèi)部開銷理論上要占用的內(nèi)存
used_memory_human:25.13M#上一數(shù)據(jù)的可讀版本
used_memory_rss:28127232##(Resident Set Size常駐數(shù)據(jù)集大形竟尽),可理解為OS為Redis分配的物理內(nèi)存總量
used_memory_rss_human:26.82M
used_memory_peak:26355360#峰值內(nèi)存
used_memory_peak_human:25.13M#峰值內(nèi)存可讀版本
total_system_memory:8253997056
total_system_memory_human:7.69G
used_memory_lua:37888#lua引擎占用內(nèi)存
used_memory_lua_human:37.00K
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
mem_fragmentation_ratio:1.07#內(nèi)存碎片率璃岳,used_memory_rss 和 used_memory 之間的比率
mem_allocator:jemalloc-4.0.3#所使用的內(nèi)存分配器年缎。可以是 libc 铃慷、 jemalloc 或者 tcmalloc
其中mem_fragmentation_ratio
(內(nèi)存碎片率)是分析Redis性能的重要數(shù)據(jù)指標(biāo)
- 大于1:OS為Redis分配的物理內(nèi)存 > Redis所有key-value值及內(nèi)部開銷應(yīng)占用的內(nèi)存
產(chǎn)生原因:物理內(nèi)存多出的部分单芜,Redis內(nèi)移除對(duì)象的占用內(nèi)存,但這部分內(nèi)存由Redis自帶內(nèi)存分配器占用犁柜,沒有向操作系統(tǒng)返回洲鸠。這一部分就是內(nèi)存碎片 - 小于1:OS為Redis分配的物理內(nèi)存 < Redis所有key-value值及內(nèi)部開銷理應(yīng)占用的內(nèi)存
產(chǎn)生原因:應(yīng)占內(nèi)存比物理內(nèi)存多出的部分,是被操作系統(tǒng)交換到虛擬內(nèi)存馋缅,說明當(dāng)前Redis的內(nèi)存使用已經(jīng)超出物理內(nèi)存
內(nèi)存碎片率保持在1.0至1.5之間是最理想的狀態(tài)扒腕。假若碎片率超過了1.5,我所知道的最有效解決手段就是重啟Redis服務(wù)器萤悴,釋放內(nèi)存回到操作系統(tǒng)瘾腰;反之,若碎片率為0.9覆履,說明物理內(nèi)存已不夠用蹋盆,應(yīng)增添硬件费薄,或設(shè)置Redis最大內(nèi)存限制maxmemory
。
最大內(nèi)存限制maxmemory
的設(shè)置非常重要栖雾,如果不設(shè)置maxmemory
义锥,Redis一直會(huì)為其分配內(nèi)存,直至耗盡所有物理內(nèi)存岩灭,直到操作系統(tǒng)進(jìn)行虛擬內(nèi)存交換。因此赂鲤,一般情況下噪径,作者建議還是把峰值設(shè)置設(shè)上。開啟此配置数初,當(dāng)超出限定內(nèi)存情況發(fā)生找爱,Redis會(huì)返回異常消息,操作系統(tǒng)不會(huì)因內(nèi)存溢出而奔潰泡孩。還有一點(diǎn)建議是车摄,開發(fā)者在系統(tǒng)設(shè)計(jì)之初,就應(yīng)當(dāng)制定Redis內(nèi)存使用劃分計(jì)劃仑鸥,而劃分原則是吮播,為Redis準(zhǔn)備系統(tǒng)可能使用的峰值內(nèi)存,而不是平均使用內(nèi)存眼俊。例如系統(tǒng)大部分情況會(huì)以Redis作為分布式緩存寫入10G數(shù)據(jù)意狠,但大部分情況下只會(huì)跑到4G,但Redis依然推薦用戶為其預(yù)留10G內(nèi)存(used_memory_peak
峰值)疮胖。
maxmemory的單位是bytes环戈,默認(rèn)為0,即不限制最大內(nèi)存澎灸。
Redis的內(nèi)存回收主要圍繞Redis的過期策略和淘汰策略來進(jìn)行的院塞,Redis中過期策略和淘汰策略是不一樣的,我們來詳細(xì)了解下兩者之間的區(qū)別:
- 過期策略
過期策略分為三種:定時(shí)過期性昭、惰性過期以及定期過期
1. 定時(shí)過期
是我們通過程序向redis中新增數(shù)據(jù)的同時(shí)就已經(jīng)設(shè)置好該數(shù)據(jù)的過期時(shí)間拦止,到了定時(shí)時(shí)間就會(huì)讓該數(shù)據(jù)失效,
這種方式對(duì)內(nèi)存友好巩梢,但是對(duì)CPU的計(jì)算相對(duì)就提高了很多创泄,這個(gè)在系統(tǒng)提供高并發(fā)服務(wù)的受到影響,并且影響系統(tǒng)的響應(yīng)和吞吐量
2. 惰性過期
所謂的惰性過期括蝠,就是我們?cè)谠L問該數(shù)據(jù)時(shí)鞠抑,在判斷該數(shù)據(jù)是否過期失效,如果過期則刪除忌警,
這種方法能大量的節(jié)省CPU的資源搁拙,但是對(duì)內(nèi)存非常不友好秒梳,可能出現(xiàn)大量的Key沒有被訪問,從而也不會(huì)刪除箕速,占用大量的內(nèi)存
3. 定期過期
每隔一段時(shí)間酪碘,就會(huì)掃描一下redis中expires字典中一定數(shù)量的key,并且清除其中已經(jīng)過期的key盐茎。
通過定時(shí)掃描的時(shí)間間隔和每次掃描的限定損耗兴垦,在不同的情況下,使得CPU和內(nèi)存資源達(dá)到相對(duì)的一種平衡
Redis中同時(shí)用了惰性過期和定期過期
- 淘汰策略
所謂淘汰策略就是當(dāng)內(nèi)存中內(nèi)存不足字柠,Redis中是達(dá)到redis.conf配置中的maxmemory
的極限時(shí)探越,需要采用LUA淘汰算法來定期清理掉哪些數(shù)據(jù)
1. LUA算法
LUA算法就是最近最少使用算法
2. 緩存清理配置
redis.conf配置中的maxmemory配置內(nèi)存達(dá)到多大時(shí),進(jìn)行內(nèi)存請(qǐng)求窑业,
在64位系統(tǒng)中钦幔,如果配置為0,則不限制內(nèi)存的使用常柄,
但是在32位系統(tǒng)中鲤氢,默認(rèn)顯示內(nèi)存大小是3G
3. Redis內(nèi)存淘汰策略
淘汰策略是有redis.conf配置中的 maxmemory-policy來控制的,其值主要有以下幾個(gè):
策略名稱 | 策略說明 |
---|---|
volatile-lru | 使用LRU算法刪除一個(gè)鍵(只對(duì)設(shè)置了生存時(shí)間的鍵) |
allkeys-lru | 使用LRU算法刪除一個(gè)鍵 |
volatile-random | 隨機(jī)刪除一個(gè)鍵(只對(duì)設(shè)置了生存時(shí)間的鍵) |
allkeys-random | 隨機(jī)刪除一個(gè)鍵 |
volatile-ttl | 刪除生存時(shí)間接近的一個(gè)鍵 |
noeviction | 不刪除鍵西潘,只返回錯(cuò)誤 |
- noeviction: 當(dāng)內(nèi)存不足時(shí)寫入新的數(shù)據(jù)卷玉,寫入操作會(huì)報(bào)錯(cuò)
- allkeys-lru: 當(dāng)不存不足時(shí)寫入新的數(shù)據(jù),在鍵空間中喷市,移除最近最少使用的key
- allkeys-random:當(dāng)不存不足時(shí)寫入新的數(shù)據(jù)揍庄,在鍵空間中,隨機(jī)移除某個(gè)key
- volatile-lru: 當(dāng)不存不足時(shí)寫入新的數(shù)據(jù)东抹,在設(shè)置過期時(shí)間的鍵中蚂子,移除最近最少使用的鍵
- volatile-random:當(dāng)不存不足時(shí)寫入新的數(shù)據(jù),在設(shè)置過期時(shí)間的鍵中缭黔,隨機(jī)移除一個(gè)鍵
- volatile-ttl:當(dāng)內(nèi)存不足時(shí)寫入新的數(shù)據(jù)食茎,在設(shè)置過期時(shí)間的鍵中,有更早過期時(shí)間的key優(yōu)先刪除
- Redis實(shí)現(xiàn)分布式鎖
在開發(fā)中鎖的概念就非常重要了馏谨,我們常接觸到的有線程鎖别渔、進(jìn)程鎖和分布式鎖。
分布式鎖就是當(dāng)多個(gè)進(jìn)程不在同一系統(tǒng)中惧互,用分布式鎖控制多個(gè)線程對(duì)資源進(jìn)行訪問哎媚。
分布式鎖不僅具有鎖的特征,還多了一下其他的特征
- 互斥性:任意時(shí)刻喊儡,只有一個(gè)客戶端獲取鎖拨与,不能同時(shí)又多個(gè)客戶端獲取鎖
- 安全性:鎖只能被持有該鎖的對(duì)象機(jī)進(jìn)行解決,獲取鎖自動(dòng)消除
- 死鎖:獲取鎖的客戶端因?yàn)槟承┰蝈礄C(jī)了而未能釋放鎖艾猜,其他的客戶端無法獲取鎖
- 容錯(cuò):當(dāng)部分節(jié)點(diǎn)宕機(jī)了买喧,客戶端仍能獲取鎖和釋放鎖
Redis實(shí)現(xiàn)分布式鎖有以下兩種方案:
1. 在操作某個(gè)記錄時(shí)捻悯,查看是否存在對(duì)應(yīng)的key記錄 ,如果存在說明該記錄被加鎖淤毛,如果沒有的話在繼續(xù)添加鎖今缚,
并且添加鎖成功之后處理自己的業(yè)務(wù)邏輯,相關(guān)的偽代碼如下
// 加鎖
function boolean lock(taskId) {
if (existsKey(taskId)) {
return false;
}else {
// 向redis中查詢新的key 設(shè)置過期時(shí)間
setKey(taskId);
return true;
}
}
// 釋放鎖
function relaseLock(taskId) {
if (existsKey(taskId)) {
delKey(taskId);
}
}
// 使用鎖
booelan lock = false;
try{
lock = lock(taskId);
if (lock) {
// 業(yè)務(wù)處理
}
}catch(Exception e) {
}finally {
if (lock) {
relaseKey(taskId);
}
}
上面的代碼會(huì)出現(xiàn)兩個(gè)問題
- 釋放鎖的代碼必須保持原子性低淡,否則在高并發(fā)的情況下會(huì)出現(xiàn)不可預(yù)知的問題姓言,不能保證鎖的互斥性
- 同一把鎖同一個(gè)時(shí)間內(nèi)可能會(huì)被其他的線程獲取到,并且由其他的線程來釋放鎖蔗蹋,不能保證鎖的安全性
2. 為了解決上述的問題事期,我們來優(yōu)化代碼,針對(duì)加鎖和釋放鎖都添加原子性操作纸颜,這樣單機(jī)版的redis環(huán)境就不會(huì)出現(xiàn)上述的問題了
Redis中支持一個(gè)語法 `SETEX key seconds value`, 該語法可以添加一個(gè)key,并且給這個(gè)key設(shè)置過期時(shí)間和value绎橘,為了達(dá)到誰加鎖胁孙,就讓誰來解鎖,
則我們可以將value設(shè)置成用戶的sessionId称鳞,并且在釋放鎖的時(shí)候確認(rèn)是否是對(duì)應(yīng)用戶進(jìn)行操作的涮较,
同時(shí)鑒于redis目前沒有針對(duì)這個(gè)業(yè)務(wù)提供具有原子性的操作指令,我們可以使用lua算法來實(shí)現(xiàn)鎖的釋放冈止,
完善后的偽代碼跟上述的代碼很像狂票,只是修改了加鎖和釋放鎖的操作,我們這里描述下lua算法:
if readdirSync.call('get', KEYS[1] == ARGV[1] then
return redis.call('del', KEYS[1]);
else
return 0;
end
該分布式鎖在單機(jī)版環(huán)境下能達(dá)到業(yè)務(wù)的需求熙暴,但是在Redis集群環(huán)境中闺属,由于Redis的主從復(fù)制時(shí)異步的,所以上述的方案在集群環(huán)境中還是有問題的
- Redis緩存和Mysql數(shù)據(jù)庫一致性的問題
在高并發(fā)的業(yè)務(wù)場景中周霉,一般都是先從緩存中讀取數(shù)據(jù)掂器,緩存中沒有的再從數(shù)據(jù)庫中讀取,并且寫入到緩存中俱箱,一般來說讀的情況還好国瓮,但是數(shù)據(jù)庫更新和緩存更新容易出現(xiàn)緩存和數(shù)據(jù)庫一致性的問題
不管是先寫數(shù)據(jù)庫,再刪除Redis緩存狞谱,還是先刪除緩存乃摹,再寫數(shù)據(jù)庫,都有可能出現(xiàn)數(shù)據(jù)不一致的問題
1. 如果先刪除緩存跟衅,還沒來得及寫入數(shù)據(jù)庫孵睬,此時(shí)又一個(gè)線程過來請(qǐng)求緩存了,發(fā)現(xiàn)緩存是空的伶跷,就會(huì)到數(shù)據(jù)庫中去請(qǐng)求肪康,此時(shí)緩存中的是臟數(shù)據(jù)
2. 如果先寫庫荚恶,在刪除緩存之前,寫庫的線程宕機(jī)了磷支,沒有刪除緩存谒撼,則此時(shí)緩存中的數(shù)據(jù)就和數(shù)據(jù)庫中的不一致
有兩種方案
- 采用延時(shí)雙刪策略
在寫庫的前后都進(jìn)行redis.del(key)的操作,并且設(shè)定合理的超時(shí)時(shí)間
具體的操作步驟:
1. 先刪除緩存
2. 再寫數(shù)據(jù)庫
3. 休眠一段時(shí)間(具體時(shí)間由業(yè)務(wù)決定雾狈,考慮讀寫庫的時(shí)間)
4. 再次刪除緩存
5. 設(shè)置緩存超時(shí)
該方案的弊端:采用上述的方案廓潜,最差的情況下在超時(shí)時(shí)間內(nèi)數(shù)據(jù)是不一致的,而且增加了寫請(qǐng)求的耗時(shí)善榛,高并發(fā)的情況下對(duì)系統(tǒng)響應(yīng)造成一定的影響辩蛋。
- 異步更新緩存(基于訂閱binlog的同步機(jī)制)
該方法的整體的思路如下:
MySql binlog增量訂閱消費(fèi)+消息隊(duì)列+增量數(shù)據(jù)更新到Redis
具體的流程如下:
mysql中一旦產(chǎn)生了新的寫入、更新移盆、刪除等操作悼院,就可以把binlog相關(guān)的消息推送至Redis,
Redis再根據(jù)binlog中的記錄咒循,對(duì)Redis進(jìn)行更新据途。其實(shí)這種機(jī)制,很類似MySQL的主從備份機(jī)制叙甸,
因?yàn)镸ySQL的主備也是通過binlog來實(shí)現(xiàn)的數(shù)據(jù)一致性颖医。
這里可以結(jié)合使用canal(阿里的一款開源框架),通過該框架可以對(duì)MySQL的binlog進(jìn)行訂閱裆蒸,
而canal正是模仿了mysql的slave數(shù)據(jù)庫的備份請(qǐng)求熔萧,使得Redis的數(shù)據(jù)更新達(dá)到了相同的效果。
當(dāng)然僚祷,這里的消息推送工具你也可以采用別的第三方:kafka佛致、rabbitMQ等來實(shí)現(xiàn)推送更新Redis。
- Redis為什么是單線程及高并發(fā)
- redis是基于內(nèi)存的辙谜,內(nèi)存的讀寫速度非成谓埽快
- 之所以設(shè)計(jì)為單線程,是為了減少上下文切換的時(shí)間
- 使用多路復(fù)用技術(shù)筷弦,可以處理并發(fā)鏈接肋演,非阻塞IO,內(nèi)部實(shí)現(xiàn)epoll+自己實(shí)現(xiàn)的簡單的時(shí)間框架,將所有的請(qǐng)求轉(zhuǎn)化為事件烂琴,不在IO上花費(fèi)時(shí)間
- Redis的注意事項(xiàng)
實(shí)際生產(chǎn)活動(dòng)中redis的注意事項(xiàng):
1. Master最好不要做任何持久化工作爹殊,如RDB內(nèi)存快照和AOF日志文件
2. 如果數(shù)據(jù)比較重要,某個(gè)Slave開啟AOF備份數(shù)據(jù)奸绷,策略設(shè)置為每秒同步一次
3. 為了主從復(fù)制的速度和連接的穩(wěn)定性梗夸,Master和Slave最好在同一個(gè)局域網(wǎng)內(nèi)
4. 盡量避免在壓力很大的主庫上增加從庫