溫馨提示×

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

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

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

發(fā)布時(shí)間:2021-01-25 15:29:59 來(lái)源:億速云 閱讀:325 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

今天就跟大家聊聊有關(guān)Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

緩存充當(dāng)數(shù)據(jù)庫(kù)熱點(diǎn)緩存

讀操作

目前的讀操作有個(gè)固定的套路,如下:

客戶(hù)端請(qǐng)求服務(wù)器的時(shí)候,發(fā)現(xiàn)如果服務(wù)器的緩存中存在,則直接取服務(wù)器的;

如果緩存中不存在,則去請(qǐng)求數(shù)據(jù)庫(kù),并且將數(shù)據(jù)庫(kù)計(jì)算出來(lái)的數(shù)據(jù)回填給緩存;

返回?cái)?shù)據(jù)給客戶(hù)端;

寫(xiě)操作

各種情況會(huì)導(dǎo)致數(shù)據(jù)庫(kù)和緩存出現(xiàn)不一致的情況,這就是緩存和數(shù)據(jù)庫(kù)的雙寫(xiě)一致性問(wèn)題;

目前緩存存在三種策略,分別是

Cache Aside 更新策略:同時(shí)更新緩存和數(shù)據(jù)庫(kù);

Read/Write Through 更新策略:先更新緩存,緩存負(fù)責(zé)同步更新數(shù)據(jù)庫(kù);

Write Behind Caching 更新策略:先更新緩存,緩存定時(shí)異步更新數(shù)據(jù)庫(kù);

三種策略各有優(yōu)缺點(diǎn),可以根據(jù)業(yè)務(wù)場(chǎng)景使用;

Cache Aside 更新策略

該策略大概的流程就是請(qǐng)求過(guò)來(lái)時(shí)先從緩存中取,如果命中緩存的話,則直接返回讀取的數(shù)據(jù);相反如果沒(méi)有命中的話,接著會(huì)從數(shù)據(jù)庫(kù)中成功獲取到數(shù)據(jù)后,再去清除緩存中的數(shù)據(jù);具體流程圖如下:

但是以上在某些特殊的情況下是存在問(wèn)題:

問(wèn)題1:先更新數(shù)據(jù)庫(kù),后更新緩存

兩個(gè)線程在高并發(fā)的情況下就會(huì)可能出現(xiàn)數(shù)據(jù)臟讀的情況:

線程A執(zhí)行寫(xiě)操作,成功更新數(shù)據(jù)庫(kù);

線程B同樣執(zhí)行和線程A一樣的操作,但是在線程A執(zhí)行更新緩存的過(guò)程中,線程B更新了新的數(shù)據(jù)庫(kù)數(shù)據(jù)到緩存中;

線程A在線程B全部操作完成以后才將相對(duì)老的數(shù)據(jù)又更新到了緩存中;

問(wèn)題2:先刪除緩存,后更新數(shù)據(jù)庫(kù)

同樣的,在高并發(fā)場(chǎng)景下同樣會(huì)出現(xiàn)臟讀的情況:

線程A成功刪除了緩存,等待更新數(shù)據(jù)庫(kù);

線程B進(jìn)行讀操作,由于此時(shí)緩存已經(jīng)被刪除了,因此線程B重新從數(shù)據(jù)庫(kù)中獲取老的數(shù)據(jù)并且更新到了緩存中;

線程A在線程B完成了整個(gè)的讀操作以后,才更新數(shù)據(jù)庫(kù),此時(shí)緩存中的數(shù)據(jù)依舊是老的數(shù)據(jù);

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

問(wèn)題3:先更新數(shù)據(jù)庫(kù),后刪除緩存

目前這是比較普遍的操作,即使它還是有可能會(huì)出現(xiàn)臟讀的情況:

線程A進(jìn)行讀操作,此時(shí)正好沒(méi)有命中緩存,接著請(qǐng)求數(shù)據(jù)庫(kù);

線程B進(jìn)行寫(xiě)操作,在線程A沒(méi)有從數(shù)據(jù)庫(kù)中獲取到數(shù)據(jù)之前,把數(shù)據(jù)寫(xiě)入到數(shù)據(jù)庫(kù)中,并且還成功刪除了緩存;

線程A在線程B完成了整個(gè)的寫(xiě)操作以后,才將相對(duì)老的數(shù)據(jù)更新到緩存中;

但是以上的情況比較不會(huì)出現(xiàn),這是因?yàn)樯鲜銮闆r需要滿(mǎn)足線程A的讀操作要慢于線程B的寫(xiě)操作,但是在現(xiàn)實(shí)過(guò)程中,讀操作通常都是要快于寫(xiě)操作得多的,但是為了避免發(fā)生以上的情況,通常都是要給緩存加上一個(gè)過(guò)期的時(shí)間;

但是設(shè)想一下,如果上面的刪除緩存失敗了怎么辦呢,這樣顯然會(huì)導(dǎo)致數(shù)據(jù)臟讀的情況,我覺(jué)得方案如下:

設(shè)置緩存的過(guò)期時(shí)間(必須要做);

提供一個(gè)保障重試機(jī)制,將哪些刪除失敗的key提供給消息隊(duì)列去消費(fèi);

從消息隊(duì)列取出這些key再次進(jìn)行刪除,失敗再次加入到消息隊(duì)列中,超過(guò)一定次數(shù)以上則人工介入;

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

但是以上情況需要在業(yè)務(wù)代碼中進(jìn)行操作,顯然得需要進(jìn)行解耦;

目前我們公司就是使用該方案,具體過(guò)程為在更新數(shù)據(jù)庫(kù)數(shù)據(jù)的時(shí)候,數(shù)據(jù)庫(kù)會(huì)以binlog日志的形式保存下來(lái),通過(guò)canal開(kāi)源軟件將binlog解析成程序語(yǔ)言可以解析的地步,接著訂閱程序獲取到這些數(shù)據(jù)以后,嘗試刪除緩存操作,如果操作失敗的話,則將其加入到消息隊(duì)列中,重復(fù)消費(fèi),當(dāng)刪除操作的失敗次數(shù)到達(dá)一定的次數(shù)以后,還是得人工介入。

Read/Write Through 更新策略

該模式下,程序只需要維護(hù)緩存即可,數(shù)據(jù)庫(kù)的同步工作交由緩存來(lái)同步更新;

該策略具體又分為兩種:

Read Through:在查詢(xún)的過(guò)程中更新緩存;

Write Through:在寫(xiě)操作的過(guò)程中如果命中緩存,則直接更新緩存,數(shù)據(jù)庫(kù)則由緩存自己同步去更新;

Write Behind Caching 更新策略

該策略只更新緩存,不會(huì)立馬更新數(shù)據(jù)庫(kù),只會(huì)在一定的時(shí)間異步的批量去操作數(shù)據(jù)庫(kù);這樣的好處在于直接操作緩存,效率極高,并且操作數(shù)據(jù)是異步的,還可以將多次的操作數(shù)據(jù)庫(kù)語(yǔ)句合并到一個(gè)事務(wù)中一起提交,因此效率很客觀;

但是,該策略沒(méi)有辦法做到數(shù)據(jù)強(qiáng)一致性,并且實(shí)現(xiàn)邏輯相對(duì)是比較復(fù)雜的,因?yàn)樗枰_認(rèn)哪些是需要更新到數(shù)據(jù)庫(kù)的,哪些是僅僅想要存儲(chǔ)在緩存中的;

比較

目前通常使用的是第一種策略中的先更新數(shù)據(jù)庫(kù),后更新緩存;其他的相較比起來(lái)實(shí)現(xiàn)都比較復(fù)雜;

最后想說(shuō)的是,緩存本來(lái)就是為了犧牲強(qiáng)一致性來(lái)提高性能的,所以肯定會(huì)存在一定的延遲時(shí)間,我們只需要保證最終的數(shù)據(jù)一致性即可;

補(bǔ)充:redis數(shù)據(jù)的同步問(wèn)題

修改redis.conf配置文件

vi redis.conf

在編輯模式下 輸入 /slaveof 來(lái)搜索

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

將slaveof啟用 即 將#刪除

依次配置所有 slave 并將進(jìn)程 kill 掉 重啟

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

查看主從信息

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

redis 集群主從同步的簡(jiǎn)單原理

Redis的復(fù)制功能是基于內(nèi)存快照的持久化策略基礎(chǔ)上的,也就是說(shuō)無(wú)論你的持久化策略選擇的是什么,只要用到了Redis的復(fù)制功能,就一定會(huì)有內(nèi)存快照發(fā)生。

當(dāng)Slave啟動(dòng)并連接到Master之后,它將主動(dòng)發(fā)送一個(gè)SYNC命令( 首先Master會(huì)啟動(dòng)一個(gè)后臺(tái)進(jìn)程,將數(shù)據(jù)快照保存到文件中[rdb文件] Master 會(huì)給Slave 發(fā)送一個(gè)

Ping命令來(lái)判斷Slave的存活狀態(tài) 當(dāng)存活時(shí) Master會(huì)將數(shù)據(jù)文件發(fā)送給Slave 并將所有寫(xiě)命令發(fā)送到Slave )。

Slave首先會(huì)將數(shù)據(jù)文件保存到本地 之后再將 數(shù)據(jù) 加載到內(nèi)存中。當(dāng)?shù)谝淮捂溄?或者是 故障后 重新連接 都會(huì)先判斷Slave的存活狀態(tài) 在做全部數(shù)據(jù)的同步 , 之后只會(huì)同步Master的寫(xiě)操作(將命令發(fā)送給Slave)

問(wèn)題:

當(dāng) Master 同步數(shù)據(jù)時(shí) 若數(shù)據(jù)量較大 而Master本身只會(huì)啟用一個(gè)后臺(tái)進(jìn)程 來(lái)對(duì)多個(gè)Slave進(jìn)行同步 , 這樣Master就會(huì)壓力過(guò)大 , 而且Slave 恢復(fù)的時(shí)間也會(huì)很慢!

redis 主從復(fù)制的優(yōu)點(diǎn):

(1)在一個(gè)Redis集群中,master負(fù)責(zé)寫(xiě)請(qǐng)求,slave負(fù)責(zé)讀請(qǐng)求,這么做一方面通過(guò)將讀請(qǐng)求分散到其他機(jī)器從而大大減少了master服務(wù)器的壓力,另一方面slave專(zhuān)注于提供讀服務(wù)從而提高了響應(yīng)和讀取速度。

(2)在一個(gè)Redis集群中,如果master宕機(jī),slave可以介入并取代master的位置,因此對(duì)于整個(gè)Redis服務(wù)來(lái)說(shuō)不至于提供不了服務(wù),這樣使得整個(gè)Redis服務(wù)足夠安全。

(3)水平增加Slave機(jī)器可以提高性能

Slave 默認(rèn)是只讀的更改:

Master 可以 讀寫(xiě)(Write and Read) 而 Slave只可以讀(read only默認(rèn)情況)也可以更改 {但是開(kāi)啟后Slave數(shù)據(jù)不會(huì)向上同步}

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

Redis的主從架構(gòu)的兩種方式:

1.主從架構(gòu):

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

2.主從從架構(gòu):

Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步

備注:

因?yàn)镾lave斷連,重連后仍然會(huì)全部同步數(shù)據(jù),所以redis2.8版本后,增加了增量復(fù)制來(lái)解決宕機(jī)后重新鏈接仍然會(huì)全部同步!

Master會(huì)維護(hù)一個(gè)環(huán)形隊(duì)列:

隊(duì)列內(nèi)存儲(chǔ):

1》:slave連接master的id值 2》:slave上一次同步的最后一個(gè)命令這樣當(dāng)斷開(kāi)重連后就不會(huì)全部同步,而只會(huì)在最后一個(gè)命令同步數(shù)據(jù)!

當(dāng)你看到這些感到redis很好,有一點(diǎn)你要你記住,redis是基于內(nèi)存的,內(nèi)存是很珍貴的,公司不會(huì)花費(fèi)大量的資源只為了讓你玩這個(gè)架構(gòu),同時(shí)推薦memcached,這個(gè)成本就比較低了,因?yàn)樗腔诖疟P(pán)的,當(dāng)然效率就會(huì)比基于內(nèi)存的redis低,同時(shí)也有和redis同樣設(shè)計(jì)風(fēng)格的非關(guān)系型數(shù)據(jù)庫(kù)SSDB就比較友善了?!?/p>

SSDB和Redis的優(yōu)缺點(diǎn)比較:

redis是內(nèi)存數(shù)據(jù)庫(kù),ssdb是面向硬盤(pán)的存儲(chǔ),二者在存儲(chǔ)格式和讀寫(xiě)方式上有著根本的不同。前面回答里提到的zrevrange 和 zrevrangebyscore慢,而zrange 和 zrangebyscore 還能接受,其實(shí)就是說(shuō)逆序遍歷比順序遍歷慢得多,其根本原因就在于逆序遍歷的時(shí)候,會(huì)多一個(gè)“記錄頭部”定位的過(guò)程,需要不斷嘗試去定位到兩條記錄的“分界點(diǎn)”,而順序遍歷的時(shí)候則不需要,因?yàn)樽x完一條記錄直接就到了下一條記錄的“分界點(diǎn)”,并且像rocksdb之類(lèi)的存儲(chǔ)引擎都會(huì)把數(shù)據(jù)長(zhǎng)度保存在記錄的元信息里,只需要按長(zhǎng)度讀取數(shù)據(jù)就可以了。

redis則不存在類(lèi)似問(wèn)題,因?yàn)樗峭耆谥羔樅推屏吭趦?nèi)存中進(jìn)行尋址來(lái)讀取數(shù)據(jù)的,尋址效率高了好多個(gè)數(shù)量級(jí)。

ssdb貌似就是一個(gè)個(gè)人項(xiàng)目,但代碼質(zhì)量還是不錯(cuò)的,整個(gè)設(shè)計(jì)思想比較簡(jiǎn)潔。ssdb的主從復(fù)制效率很低。

binlog和數(shù)據(jù)是分開(kāi)存儲(chǔ)的,日志冗余較多,由于ssdb本身要在多線程條件下才能發(fā)揮出更好的性能,為了使多個(gè)線程在寫(xiě)入binlog時(shí)能保證操作順序和原子性,ssdb的binlog數(shù)據(jù)結(jié)構(gòu)上用了一把全局鎖,可想而知,這里的鎖競(jìng)爭(zhēng)會(huì)很影響性能。另外,ssdb默認(rèn)也沒(méi)有集群管理的支持。

ssdb的好處,和swapdb一樣,都可以省錢(qián)。如果有需要,可以嘗試swapdb,它結(jié)合了redis和ssdb的優(yōu)點(diǎn),實(shí)現(xiàn)了基于LFU的熱度統(tǒng)計(jì)和冷熱交換,做到了低成本和高性能的高平衡。redis的好處,那就多了。

缺點(diǎn)就是純內(nèi)存,比用SSD花錢(qián)。

看完上述內(nèi)容,你們對(duì)Redis數(shù)據(jù)怎么實(shí)現(xiàn)數(shù)據(jù)同步有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

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

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

AI