一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

使用Redis時(shí)可能遇到哪些「坑」?

數(shù)據(jù)分析與開(kāi)發(fā) ? 來(lái)源:水滴與銀彈 ? 作者:Kaito ? 2021-04-09 11:19 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

這篇文章,我想和你聊一聊在使用 Redis 時(shí),可能會(huì)踩到的「坑」。

如果你在使用 Redis 時(shí),也遇到過(guò)以下這些「詭異」的場(chǎng)景,那很大概率是踩到「坑」了:

明明一個(gè) key 設(shè)置了過(guò)期時(shí)間,怎么變成不過(guò)期了?

使用 O(1) 復(fù)雜度的 SETBIT 命令,Redis 竟然被 OOM 了?

執(zhí)行 RANDOMKEY 隨機(jī)拿出一個(gè) key,竟然也會(huì)阻塞 Redis?

同樣的命令,為什么主庫(kù)查不到數(shù)據(jù),從庫(kù)卻可以查到?

從庫(kù)內(nèi)存為什么比主庫(kù)用得還多?

寫(xiě)入到 Redis 的數(shù)據(jù),為什么莫名其妙丟了?

究竟是什么原因,導(dǎo)致的這些問(wèn)題呢?

這篇文章,我就來(lái)和你盤(pán)點(diǎn)一下,使用 Redis 時(shí)可能會(huì)踩到「坑」,以及如何去規(guī)避。

我把這些問(wèn)題劃分成了三大部分:

常見(jiàn)命令有哪些坑?

數(shù)據(jù)持久化有哪些坑?

主從庫(kù)同步有哪些坑?

導(dǎo)致這些問(wèn)題的原因,很有可能會(huì)「顛覆」你的認(rèn)知,如果你準(zhǔn)備好了,那就跟著我的思路開(kāi)始吧!

這篇文章干貨很多,希望你可以耐心讀完。

234bbb1e-9878-11eb-8b86-12bb97331649.png

常見(jiàn)命令有哪些坑?

首先,我們來(lái)看一下,平時(shí)在使用 Redis 時(shí),有哪些常見(jiàn)的命令會(huì)遇到「意料之外」的結(jié)果。

1) 過(guò)期時(shí)間意外丟失?

你在使用 Redis 時(shí),肯定經(jīng)常使用 SET 命令,它非常簡(jiǎn)單。

SET 除了可以設(shè)置 key-value 之外,還可以設(shè)置 key 的過(guò)期時(shí)間,就像下面這樣:

127.0.0.1:6379》 SET testkey val1 EX 60 OK 127.0.0.1:6379》 TTL testkey (integer) 59

此時(shí)如果你想修改 key 的值,但只是單純地使用 SET 命令,而沒(méi)有加上「過(guò)期時(shí)間」的參數(shù),那這個(gè) key 的過(guò)期時(shí)間將會(huì)被「擦除」。

127.0.0.1:6379》 SET testkey val2 OK 127.0.0.1:6379》 TTL testkey // key永遠(yuǎn)不過(guò)期了! (integer) -1

看到了么?testkey 變成永遠(yuǎn)不過(guò)期了!

2380d3e4-9878-11eb-8b86-12bb97331649.jpg

如果你剛剛開(kāi)始使用 Redis,相信你肯定也踩過(guò)這個(gè)坑。

導(dǎo)致這個(gè)問(wèn)題的原因在于:SET 命令如果不設(shè)置過(guò)期時(shí)間,那么 Redis 會(huì)自動(dòng)「擦除」這個(gè) key 的過(guò)期時(shí)間。

如果你發(fā)現(xiàn) Redis 的內(nèi)存持續(xù)增長(zhǎng),而且很多 key 原來(lái)設(shè)置了過(guò)期時(shí)間,后來(lái)發(fā)現(xiàn)過(guò)期時(shí)間丟失了,很有可能是因?yàn)檫@個(gè)原因?qū)е碌摹?/p>

這時(shí)你的 Redis 中就會(huì)存在大量不過(guò)期的 key,消耗過(guò)多的內(nèi)存資源。

所以,你在使用 SET 命令時(shí),如果剛開(kāi)始就設(shè)置了過(guò)期時(shí)間,那么之后修改這個(gè) key,也務(wù)必要加上過(guò)期時(shí)間的參數(shù),避免過(guò)期時(shí)間丟失問(wèn)題。

2) DEL 竟然也會(huì)阻塞 Redis?

刪除一個(gè) key,你肯定會(huì)用 DEL 命令,不知道你沒(méi)有思考過(guò)它的時(shí)間復(fù)雜度是多少?

O(1)?其實(shí)不一定。

如果你有認(rèn)真閱讀 Redis 的官方文檔,就會(huì)發(fā)現(xiàn):刪除一個(gè) key 的耗時(shí),與這個(gè) key 的類型有關(guān)。

Redis 官方文檔在介紹 DEL 命令時(shí),是這樣描述的:

key 是 String 類型,DEL 時(shí)間復(fù)雜度是 O(1)

key 是 List/Hash/Set/ZSet 類型,DEL 時(shí)間復(fù)雜度是 O(M),M 為元素?cái)?shù)量

也就是說(shuō),如果你要?jiǎng)h除的是一個(gè)非 String 類型的 key,這個(gè) key 的元素越多,那么在執(zhí)行 DEL 時(shí)耗時(shí)就越久!

為什么會(huì)這樣?

原因在于,刪除這種 key 時(shí),Redis 需要依次釋放每個(gè)元素的內(nèi)存,元素越多,這個(gè)過(guò)程就會(huì)越耗時(shí)。

而這么長(zhǎng)的操作耗時(shí),勢(shì)必會(huì)阻塞整個(gè) Redis 實(shí)例,影響 Redis 的性能。

23a2000a-9878-11eb-8b86-12bb97331649.jpg

所以,當(dāng)你在刪除 List/Hash/Set/ZSet 類型的 key 時(shí),一定要格外注意,不能無(wú)腦執(zhí)行 DEL,而是應(yīng)該用以下方式刪除:

查詢?cè)財(cái)?shù)量:執(zhí)行 LLEN/HLEN/SCARD/ZCARD 命令

判斷元素?cái)?shù)量:如果元素?cái)?shù)量較少,可直接執(zhí)行 DEL 刪除,否則分批刪除

分批刪除:執(zhí)行 LRANGE/HSCAN/SSCAN/ZSCAN + LPOP/RPOP/HDEL/SREM/ZREM 刪除

了解了 DEL 對(duì)于 List/Hash/Set/ZSet 類型數(shù)據(jù)的影響,我們?cè)賮?lái)分析下,刪除一個(gè) String 類型的 key 會(huì)不會(huì)有這種問(wèn)題?

???前面不是提到,Redis 官方文檔的描述,刪除 String 類型的 key,時(shí)間復(fù)雜度是 O(1) 么?這不會(huì)導(dǎo)致 Redis 阻塞吧?

其實(shí)這也不一定!

你思考一下,如果這個(gè) key 占用的內(nèi)存非常大呢?

例如,這個(gè) key 存儲(chǔ)了 500MB 的數(shù)據(jù)(很明顯,它是一個(gè) bigkey),那在執(zhí)行 DEL 時(shí),耗時(shí)依舊會(huì)變長(zhǎng)!

這是因?yàn)?,Redis 釋放這么大的內(nèi)存給操作系統(tǒng),也是需要時(shí)間的,所以操作耗時(shí)也會(huì)變長(zhǎng)。

所以,對(duì)于 String 類型來(lái)說(shuō),你最好也不要存儲(chǔ)過(guò)大的數(shù)據(jù),否則在刪除它時(shí),也會(huì)有性能問(wèn)題。

此時(shí),你可能會(huì)想:Redis 4.0 不是推出了 lazy-free 機(jī)制么?打開(kāi)這個(gè)機(jī)制,釋放內(nèi)存的操作會(huì)放到后臺(tái)線程中執(zhí)行,那是不是就不會(huì)阻塞主線程了?

這個(gè)問(wèn)題非常好。

真的會(huì)是這樣嗎?

這里我先告訴你結(jié)論:即使 Redis 打開(kāi)了 lazy-free,在刪除一個(gè) String 類型的 bigkey 時(shí),它仍舊是在主線程中處理,而不是放到后臺(tái)線程中執(zhí)行。所以,依舊有阻塞 Redis 的風(fēng)險(xiǎn)!

這是為什么?

這里先賣一個(gè)關(guān)子,感興趣的同學(xué)可以先自行查閱 lazy-free 相關(guān)資料尋找答案。:)

其實(shí),關(guān)于 lazy-free 的知識(shí)點(diǎn)也很多,由于篇幅原因,所以我打算后面專門(mén)寫(xiě)一篇文章來(lái)講,歡迎持續(xù)關(guān)注~

3) RANDOMKEY 竟然也會(huì)阻塞 Redis?

如果你想隨機(jī)查看 Redis 中的一個(gè) key,通常會(huì)使用 RANDOMKEY 這個(gè)命令。

這個(gè)命令會(huì)從 Redis 中「隨機(jī)」取出一個(gè) key。

既然是隨機(jī),那這個(gè)執(zhí)行速度肯定非常快吧?

其實(shí)不然。

要解釋清楚這個(gè)問(wèn)題,就要結(jié)合 Redis 的過(guò)期策略來(lái)講。

如果你對(duì) Redis 的過(guò)期策略有所了解,應(yīng)該知道 Redis 清理過(guò)期 key,是采用定時(shí)清理 + 懶惰清理 2 種方式結(jié)合來(lái)做的。

而 RANDOMKEY 在隨機(jī)拿出一個(gè) key 后,首先會(huì)先檢查這個(gè) key 是否已過(guò)期。

如果該 key 已經(jīng)過(guò)期,那么 Redis 會(huì)刪除它,這個(gè)過(guò)程就是懶惰清理。

但清理完了還不能結(jié)束,Redis 還要找出一個(gè)「不過(guò)期」的 key,返回給客戶端。

此時(shí),Redis 則會(huì)繼續(xù)隨機(jī)拿出一個(gè) key,然后再判斷是它否過(guò)期,直到找出一個(gè)未過(guò)期的 key 返回給客戶端。

整個(gè)流程就是這樣的:

master 隨機(jī)取出一個(gè) key,判斷是否已過(guò)期

如果 key 已過(guò)期,刪除它,繼續(xù)隨機(jī)取 key

以此循環(huán)往復(fù),直到找到一個(gè)不過(guò)期的 key,返回

但這里就有一個(gè)問(wèn)題了:如果此時(shí) Redis 中,有大量 key 已經(jīng)過(guò)期,但還未來(lái)得及被清理掉,那這個(gè)循環(huán)就會(huì)持續(xù)很久才能結(jié)束,而且,這個(gè)耗時(shí)都花費(fèi)在了清理過(guò)期 key + 尋找不過(guò)期 key 上。

導(dǎo)致的結(jié)果就是,RANDOMKEY 執(zhí)行耗時(shí)變長(zhǎng),影響 Redis 性能。

23b26f80-9878-11eb-8b86-12bb97331649.jpg

以上流程,其實(shí)是在 master 上執(zhí)行的。

如果在 slave 上執(zhí)行 RANDOMEKY,那么問(wèn)題會(huì)更嚴(yán)重!

為什么?

主要原因就在于,slave 自己是不會(huì)清理過(guò)期 key。

那 slave 什么時(shí)候刪除過(guò)期 key 呢?

其實(shí),當(dāng)一個(gè) key 要過(guò)期時(shí),master 會(huì)先清理刪除它,之后 master 向 slave 發(fā)送一個(gè) DEL 命令,告知 slave 也刪除這個(gè) key,以此達(dá)到主從庫(kù)的數(shù)據(jù)一致性。

還是同樣的場(chǎng)景:Redis 中存在大量已過(guò)期,但還未被清理的 key,那在 slave 上執(zhí)行 RANDOMKEY 時(shí),就會(huì)發(fā)生以下問(wèn)題:

slave 隨機(jī)取出一個(gè) key,判斷是否已過(guò)期

key 已過(guò)期,但 slave 不會(huì)刪除它,而是繼續(xù)隨機(jī)尋找不過(guò)期的 key

由于大量 key 都已過(guò)期,那 slave 就會(huì)尋找不到符合條件的 key,此時(shí)就會(huì)陷入「死循環(huán)」!

也就是說(shuō),在 slave 上執(zhí)行 RANDOMKEY,有可能會(huì)造成整個(gè) Redis 實(shí)例卡死!

23ca87a0-9878-11eb-8b86-12bb97331649.jpg

是不是沒(méi)想到?在 slave 上隨機(jī)拿一個(gè) key,竟然有可能造成這么嚴(yán)重的后果?

這其實(shí)是 Redis 的一個(gè) Bug,這個(gè) Bug 一直持續(xù)到 5.0 才被修復(fù)。

修復(fù)的解決方案是,在 slave 上執(zhí)行 RANDOMKEY 時(shí),會(huì)先判斷整個(gè)實(shí)例所有 key 是否都設(shè)置了過(guò)期時(shí)間,如果是,為了避免長(zhǎng)時(shí)間找不到符合條件的 key,slave 最多只會(huì)在哈希表中尋找 100 次,無(wú)論是否能找到,都會(huì)退出循環(huán)。

這個(gè)方案就是增加上了一個(gè)最大重試次數(shù),這樣一來(lái),就避免了陷入死循環(huán)。

23e031a4-9878-11eb-8b86-12bb97331649.jpg

雖然這個(gè)方案可以避免了 slave 陷入死循環(huán)、卡死整個(gè)實(shí)例的問(wèn)題,但是,在 master 上執(zhí)行這個(gè)命令時(shí),依舊有概率導(dǎo)致耗時(shí)變長(zhǎng)。

所以,你在使用 RANDOMKEY 時(shí),如果發(fā)現(xiàn) Redis 發(fā)生了「抖動(dòng)」,很有可能是因?yàn)檫@個(gè)原因?qū)е碌模?/p>

4) O(1) 復(fù)雜度的 SETBIT,竟然會(huì)導(dǎo)致 Redis OOM?

在使用 Redis 的 String 類型時(shí),除了直接寫(xiě)入一個(gè)字符串之外,還可以把它當(dāng)做 bitmap 來(lái)用。

具體來(lái)講就是,我們可以把一個(gè) String 類型的 key,拆分成一個(gè)個(gè) bit 來(lái)操作,就像下面這樣:

127.0.0.1:6379》 SETBIT testkey 10 1 (integer) 1 127.0.0.1:6379》 GETBIT testkey 10 (integer) 1

23f2ce36-9878-11eb-8b86-12bb97331649.jpg

其中,操作的每一個(gè) bit 位叫做 offset。

但是,這里有一個(gè)坑,你需要注意起來(lái)。

如果這個(gè) key 不存在,或者 key 的內(nèi)存使用很小,此時(shí)你要操作的 offset 非常大,那么 Redis 就需要分配「更大的內(nèi)存空間」,這個(gè)操作耗時(shí)就會(huì)變長(zhǎng),影響性能。

24054cc8-9878-11eb-8b86-12bb97331649.jpg

所以,當(dāng)你在使用 SETBIT 時(shí),也一定要注意 offset 的大小,操作過(guò)大的 offset 也會(huì)引發(fā) Redis 卡頓。

這種類型的 key,也是典型的 bigkey,除了分配內(nèi)存影響性能之外,在刪除它時(shí),耗時(shí)同樣也會(huì)變長(zhǎng)。

5) 執(zhí)行 MONITOR 也會(huì)導(dǎo)致 Redis OOM?

這個(gè)坑你肯定聽(tīng)說(shuō)過(guò)很多次了。

當(dāng)你在執(zhí)行 MONITOR 命令時(shí),Redis 會(huì)把每一條命令寫(xiě)到客戶端的「輸出緩沖區(qū)」中,然后客戶端從這個(gè)緩沖區(qū)讀取服務(wù)端返回的結(jié)果。

240e0f8e-9878-11eb-8b86-12bb97331649.jpg

但是,如果你的 Redis QPS 很高,這將會(huì)導(dǎo)致這個(gè)輸出緩沖區(qū)內(nèi)存持續(xù)增長(zhǎng),占用 Redis 大量的內(nèi)存資源,如果恰好你的機(jī)器的內(nèi)存資源不足,那 Redis 實(shí)例就會(huì)面臨被 OOM 的風(fēng)險(xiǎn)。

所以,你需要謹(jǐn)慎使用 MONITOR,尤其在 QPS 很高的情況下。

以上這些問(wèn)題場(chǎng)景,都是我們?cè)谑褂贸R?jiàn)命令時(shí)發(fā)生的,而且,很可能都是「無(wú)意」就會(huì)觸發(fā)的。

下面我們來(lái)看 Redis「數(shù)據(jù)持久化」都存在哪些坑?

數(shù)據(jù)持久化有哪些坑?

Redis 的數(shù)據(jù)持久化,分為 RDB 和 AOF 兩種方式。

其中,RDB 是數(shù)據(jù)快照,而 AOF 會(huì)記錄每一個(gè)寫(xiě)命令到日志文件中。

在數(shù)據(jù)持久化方面發(fā)生問(wèn)題,主要也集中在這兩大塊,我們依次來(lái)看。

1) master 宕機(jī),slave 數(shù)據(jù)也丟失了?

如果你的 Redis 采用如下模式部署,就會(huì)發(fā)生數(shù)據(jù)丟失的問(wèn)題:

master-slave + 哨兵部署實(shí)例

master 沒(méi)有開(kāi)啟數(shù)據(jù)持久化功能

Redis 進(jìn)程使用 supervisor 管理,并配置為「進(jìn)程宕機(jī),自動(dòng)重啟」

如果此時(shí) master 宕機(jī),就會(huì)導(dǎo)致下面的問(wèn)題:

master 宕機(jī),哨兵還未發(fā)起切換,此時(shí) master 進(jìn)程立即被 supervisor 自動(dòng)拉起

但 master 沒(méi)有開(kāi)啟任何數(shù)據(jù)持久化,啟動(dòng)后是一個(gè)「空」實(shí)例

此時(shí) slave 為了與 master 保持一致,它會(huì)自動(dòng)「清空」實(shí)例中的所有數(shù)據(jù),slave 也變成了一個(gè)「空」實(shí)例

看到了么?在這個(gè)場(chǎng)景下,master / slave 的數(shù)據(jù)就全部丟失了。

這時(shí),業(yè)務(wù)應(yīng)用在訪問(wèn) Redis 時(shí),發(fā)現(xiàn)緩存中沒(méi)有任何數(shù)據(jù),就會(huì)把請(qǐng)求全部打到后端數(shù)據(jù)庫(kù)上,這還會(huì)進(jìn)一步引發(fā)「緩存雪崩」,對(duì)業(yè)務(wù)影響非常大。

所以,你一定要避免這種情況發(fā)生,我給你的建議是:

Redis 實(shí)例不使用進(jìn)程管理工具自動(dòng)拉起

master 宕機(jī)后,讓哨兵發(fā)起切換,把 slave 提升為 master

切換完成后,再重啟 master,讓其退化成 slave

你在配置數(shù)據(jù)持久化時(shí),要避免這個(gè)問(wèn)題的發(fā)生。

2) AOF everysec 真的不會(huì)阻塞主線程嗎?

當(dāng) Redis 開(kāi)啟 AOF 時(shí),需要配置 AOF 的刷盤(pán)策略。

基于性能和數(shù)據(jù)安全的平衡,你肯定會(huì)采用 appendfsync everysec 這種方案。

這種方案的工作模式為,Redis 的后臺(tái)線程每間隔 1 秒,就把 AOF page cache 的數(shù)據(jù),刷到磁盤(pán)(fsync)上。

這種方案的優(yōu)勢(shì)在于,把 AOF 刷盤(pán)的耗時(shí)操作,放到了后臺(tái)線程中去執(zhí)行,避免了對(duì)主線程的影響。

但真的不會(huì)影響主線程嗎?

答案是否定的。

其實(shí)存在這樣一種場(chǎng)景:Redis 后臺(tái)線程在執(zhí)行 AOF page cache 刷盤(pán)(fysnc)時(shí),如果此時(shí)磁盤(pán) IO 負(fù)載過(guò)高,那么調(diào)用 fsync 就會(huì)被阻塞住。

此時(shí),主線程仍然接收寫(xiě)請(qǐng)求進(jìn)來(lái),那么此時(shí)的主線程會(huì)先判斷,上一次后臺(tái)線程是否已刷盤(pán)成功。

如何判斷呢?

后臺(tái)線程在刷盤(pán)成功后,都會(huì)記錄刷盤(pán)的時(shí)間。

主線程會(huì)根據(jù)這個(gè)時(shí)間來(lái)判斷,距離上一次刷盤(pán)已經(jīng)過(guò)去多久了。整個(gè)流程是這樣的:

主線程在寫(xiě) AOF page cache(write系統(tǒng)調(diào)用)前,先檢查后臺(tái) fsync 是否已完成?

fsync 已完成,主線程直接寫(xiě) AOF page cache

fsync 未完成,則檢查距離上次 fsync 過(guò)去多久?

如果距離上次 fysnc 成功在 2 秒內(nèi),那么主線程會(huì)直接返回,不寫(xiě) AOF page cache

如果距離上次 fysnc 成功超過(guò)了 2 秒,那主線程會(huì)強(qiáng)制寫(xiě) AOF page cache(write系統(tǒng)調(diào)用)

由于磁盤(pán) IO 負(fù)載過(guò)高,此時(shí),后臺(tái)線程 fynsc 會(huì)發(fā)生阻塞,那主線程在寫(xiě) AOF page cache 時(shí),也會(huì)發(fā)生阻塞等待(操作同一個(gè) fd,fsync 和 write 是互斥的,一方必須等另一方成功才可以繼續(xù)執(zhí)行,否則阻塞等待)

2721fdfc-9878-11eb-8b86-12bb97331649.jpg

通過(guò)分析我們可以發(fā)現(xiàn),即使你配置的 AOF 刷盤(pán)策略是 appendfsync everysec,也依舊會(huì)有阻塞主線程的風(fēng)險(xiǎn)。

其實(shí),產(chǎn)生這個(gè)問(wèn)題的重點(diǎn)在于,磁盤(pán) IO 負(fù)載過(guò)高導(dǎo)致 fynsc 阻塞,進(jìn)而導(dǎo)致主線程寫(xiě) AOF page cache 也發(fā)生阻塞。

所以,你一定要保證磁盤(pán)有充足的 IO 資源,避免這個(gè)問(wèn)題。

3) AOF everysec 真的只會(huì)丟失 1 秒數(shù)據(jù)?

接著上面的問(wèn)題繼續(xù)分析。

如上所述,這里我們需要重點(diǎn)關(guān)注上面的步驟 4。

也就是:主線程在寫(xiě) AOF page cache 時(shí),會(huì)先判斷上一次 fsync 成功的時(shí)間,如果距離上次 fysnc 成功在 2 秒內(nèi),那么主線程會(huì)直接返回,不再寫(xiě) AOF page cache。

這就意味著,后臺(tái)線程在執(zhí)行 fsync 刷盤(pán)時(shí),主線程最多等待 2 秒不會(huì)寫(xiě) AOF page cache。

如果此時(shí) Redis 發(fā)生了宕機(jī),那么,AOF 文件中丟失是 2 秒的數(shù)據(jù),而不是 1 秒!

我們繼續(xù)分析,Redis 主線程為什么要等待 2 秒不寫(xiě) AOF page cache 呢?

其實(shí),Redis AOF 配置為 appendfsync everysec 時(shí),正常來(lái)講,后臺(tái)線程每隔 1 秒執(zhí)行一次 fsync 刷盤(pán),如果磁盤(pán)資源充足,是不會(huì)被阻塞住的。

也就是說(shuō),Redis 主線程其實(shí)根本不用關(guān)心后臺(tái)線程是否刷盤(pán)成功,只要無(wú)腦寫(xiě) AOF page cache 即可。

但是,Redis 作者考慮到,如果此時(shí)的磁盤(pán) IO 資源比較緊張,那么后臺(tái)線程 fsync 就有概率發(fā)生阻塞風(fēng)險(xiǎn)。

所以,Redis 作者在主線程寫(xiě) AOF page cache 之前,先檢查一下距離上一次 fsync 成功的時(shí)間,如果大于 1 秒沒(méi)有成功,那么主線程此時(shí)就能知道,fsync 可能阻塞了。

所以,主線程會(huì)等待 2 秒不寫(xiě) AOF page cache,其目的在于:

降低主線程阻塞的風(fēng)險(xiǎn)(如果無(wú)腦寫(xiě) AOF page cache,主線程則會(huì)立即阻塞住)

如果 fsync 阻塞,主線程就會(huì)給后臺(tái)線程留出 1 秒的時(shí)間,等待 fsync 成功

但代價(jià)就是,如果此時(shí)發(fā)生宕機(jī),AOF 丟失的就是 2 秒的數(shù)據(jù),而不是 1 秒。

這個(gè)方案應(yīng)該是 Redis 作者對(duì)性能和數(shù)據(jù)安全性的進(jìn)一步權(quán)衡。

無(wú)論如何,這里你只需要知道的是,即使 AOF 配置為每秒刷盤(pán),在發(fā)生上述極端情況時(shí),AOF 丟失的數(shù)據(jù)其實(shí)是 2 秒。

4) RDB 和 AOF rewrite 時(shí),Redis 發(fā)生 OOM?

最后,我們來(lái)看一下,當(dāng) Redis 在執(zhí)行 RDB 快照和 AOF rewrite 時(shí),會(huì)發(fā)生的問(wèn)題。

Redis 在做 RDB 快照和 AOF rewrite 時(shí),會(huì)采用創(chuàng)建子進(jìn)程的方式,把實(shí)例中的數(shù)據(jù)持久化到磁盤(pán)上。

創(chuàng)建子進(jìn)程,會(huì)調(diào)用操作系統(tǒng)的 fork 函數(shù)。

fork 執(zhí)行完成后,父進(jìn)程和子進(jìn)程會(huì)同時(shí)共享同一份內(nèi)存數(shù)據(jù)。

但此時(shí)的主進(jìn)程依舊是可以接收寫(xiě)請(qǐng)求的,而進(jìn)來(lái)的寫(xiě)請(qǐng)求,會(huì)采用 Copy On Write(寫(xiě)時(shí)復(fù)制)的方式操作內(nèi)存數(shù)據(jù)。

也就是說(shuō),主進(jìn)程一旦有數(shù)據(jù)需要修改,Redis 并不會(huì)直接修改現(xiàn)有內(nèi)存中的數(shù)據(jù),而是先將這塊內(nèi)存數(shù)據(jù)拷貝出來(lái),再修改這塊新內(nèi)存的數(shù)據(jù),這就是所謂的「寫(xiě)時(shí)復(fù)制」。

寫(xiě)時(shí)復(fù)制你也可以理解成,誰(shuí)需要發(fā)生寫(xiě)操作,誰(shuí)就先拷貝,再修改。

你應(yīng)該發(fā)現(xiàn)了,如果父進(jìn)程要修改一個(gè) key,就需要拷貝原有的內(nèi)存數(shù)據(jù),到新內(nèi)存中,這個(gè)過(guò)程涉及到了「新內(nèi)存」的申請(qǐng)。

如果你的業(yè)務(wù)特點(diǎn)是「寫(xiě)多讀少」,而且 OPS 非常高,那在 RDB 和 AOF rewrite 期間,就會(huì)產(chǎn)生大量的內(nèi)存拷貝工作。

這會(huì)有什么問(wèn)題呢?

因?yàn)閷?xiě)請(qǐng)求很多,這會(huì)導(dǎo)致 Redis 父進(jìn)程會(huì)申請(qǐng)非常多的內(nèi)存。在這期間,修改 key 的范圍越廣,新內(nèi)存的申請(qǐng)就越多。

如果你的機(jī)器內(nèi)存資源不足,這就會(huì)導(dǎo)致 Redis 面臨被 OOM 的風(fēng)險(xiǎn)!

27512d5c-9878-11eb-8b86-12bb97331649.jpg

這就是你會(huì)從 DBA 同學(xué)那里聽(tīng)到的,要給 Redis 機(jī)器預(yù)留內(nèi)存的原因。

其目的就是避免在 RDB 和 AOF rewrite 期間,防止 Redis OOM。

以上這些,就是「數(shù)據(jù)持久化」會(huì)遇到的坑,你踩到過(guò)幾個(gè)?

下面我們?cè)賮?lái)看「主從復(fù)制」會(huì)存在哪些問(wèn)題。

主從復(fù)制有哪些坑?

Redis 為了保證高可用,提供了主從復(fù)制的方式,這樣就可以保證 Redis 有多個(gè)「副本」,當(dāng)主庫(kù)宕機(jī)后,我們依舊有從庫(kù)可以使用。

在主從同步期間,依舊存在很多坑,我們依次來(lái)看。

1) 主從復(fù)制會(huì)丟數(shù)據(jù)嗎?

首先,你需要知道,Redis 的主從復(fù)制是采用「異步」的方式進(jìn)行的。

這就意味著,如果 master 突然宕機(jī),可能存在有部分?jǐn)?shù)據(jù)還未同步到 slave 的情況發(fā)生。

這會(huì)導(dǎo)致什么問(wèn)題呢?

如果你把 Redis 當(dāng)做純緩存來(lái)使用,那對(duì)業(yè)務(wù)來(lái)說(shuō)沒(méi)有什么影響。

master 未同步到 slave 的數(shù)據(jù),業(yè)務(wù)應(yīng)用可以從后端數(shù)據(jù)庫(kù)中重新查詢到。

但是,對(duì)于把 Redis 當(dāng)做數(shù)據(jù)庫(kù),或是當(dāng)做分布式鎖來(lái)使用的業(yè)務(wù),有可能因?yàn)楫惒綇?fù)制的問(wèn)題,導(dǎo)致數(shù)據(jù)丟失 / 鎖丟失。

關(guān)于 Redis 分布式鎖可靠性的更多細(xì)節(jié),這里先不展開(kāi),后面會(huì)單獨(dú)寫(xiě)一篇文章詳細(xì)剖析這個(gè)知識(shí)點(diǎn)。這里你只需要先知道,Redis 主從復(fù)制是有概率發(fā)生數(shù)據(jù)丟失的。

2) 同樣命令查詢一個(gè) key,主從庫(kù)卻返回不同的結(jié)果?

不知道你是否思考過(guò)這樣一個(gè)問(wèn)題:如果一個(gè) key 已過(guò)期,但這個(gè) key 還未被 master 清理,此時(shí)在 slave 上查詢這個(gè) key,會(huì)返回什么結(jié)果呢?

slave 正常返回 key 的值

slave 返回 NULL

你認(rèn)為是哪一種?可以思考一下。

答案是:不一定。

嗯?為什么會(huì)不一定?

這個(gè)問(wèn)題非常有意思,請(qǐng)跟緊我的思路,我會(huì)帶你一步步分析其中的原因。

其實(shí),返回什么結(jié)果,這要取決于以下 3 個(gè)因素:

Redis 的版本

具體執(zhí)行的命令

機(jī)器時(shí)鐘

先來(lái)看 Redis 版本。

如果你使用的是 Redis 3.2 以下版本,只要這個(gè) key 還未被 master 清理,那么,在 slave 上查詢這個(gè) key,它會(huì)永遠(yuǎn)返回 value 給你。

也就是說(shuō),即使這個(gè) key 已過(guò)期,在 slave 上依舊可以查詢到這個(gè) key。

// Redis 2.8 版本 在 slave 上執(zhí)行 127.0.0.1:6479》 TTL testkey (integer) -2 // 已過(guò)期 127.0.0.1:6479》 GET testkey “testval” // 還能查詢到!

但如果此時(shí)在 master 上查詢這個(gè) key,發(fā)現(xiàn)已經(jīng)過(guò)期,就會(huì)把它清理掉,然后返回 NULL。

// Redis 2.8 版本 在 master 上執(zhí)行 127.0.0.1:6379》 TTL testkey (integer) -2 127.0.0.1:6379》 GET testkey (nil)

發(fā)現(xiàn)了嗎?在 master 和 slave 上查詢同一個(gè) key,結(jié)果竟然不一樣?

其實(shí),slave 應(yīng)該要與 master 保持一致,key 已過(guò)期,就應(yīng)該給客戶端返回 NULL,而不是還正常返回 key 的值。

為什么會(huì)發(fā)生這種情況?

其實(shí)這是 Redis 的一個(gè) Bug:3.2 以下版本的 Redis,在 slave 上查詢一個(gè) key 時(shí),并不會(huì)判斷這個(gè) key 是否已過(guò)期,而是直接無(wú)腦返回給客戶端結(jié)果。

這個(gè) Bug 在 3.2 版本進(jìn)行了修復(fù),但是,它修復(fù)得「不夠徹底」。

什么叫修復(fù)得「不夠徹底」?

這就要結(jié)合前面提到的,第 2 個(gè)影響因素「具體執(zhí)行的命令」來(lái)解釋了。

Redis 3.2 雖然修復(fù)了這個(gè) Bug,但卻遺漏了一個(gè)命令:EXISTS。

也就是說(shuō),一個(gè) key 已過(guò)期,在 slave 直接查詢它的數(shù)據(jù),例如執(zhí)行 GET/LRANGE/HGETALL/SMEMBERS/ZRANGE 這類命令時(shí),slave 會(huì)返回 NULL。

但如果執(zhí)行的是 EXISTS,slave 依舊會(huì)返回:key 還存在。

// Redis 3.2 版本 在 slave 上執(zhí)行 127.0.0.1:6479》 GET testkey (nil) // key 已邏輯過(guò)期 127.0.0.1:6479》 EXISTS testkey (integer) 1 // 還存在!

原因在于,EXISTS 與查詢數(shù)據(jù)的命令,使用的不是同一個(gè)方法。

Redis 作者只在查詢數(shù)據(jù)時(shí)增加了過(guò)期時(shí)間的校驗(yàn),但 EXISTS 命令依舊沒(méi)有這么做。

直到 Redis 4.0.11 這個(gè)版本,Redis 才真正把這個(gè)遺漏的 Bug 完全修復(fù)。

如果你使用的是這個(gè)之上的版本,那在 slave 上執(zhí)行數(shù)據(jù)查詢或 EXISTS,對(duì)于已過(guò)期的 key,就都會(huì)返回「不存在」了。

這里我們先小結(jié)一下,slave 查詢過(guò)期 key,經(jīng)歷了 3 個(gè)階段:

3.2 以下版本,key 過(guò)期未被清理,無(wú)論哪個(gè)命令,查詢 slave,均正常返回 value

3.2 - 4.0.11 版本,查詢數(shù)據(jù)返回 NULL,但 EXISTS 依舊返回 true

4.0.11 以上版本,所有命令均已修復(fù),過(guò)期 key 在 slave 上查詢,均返回「不存在」

這里要特別鳴謝《Redis開(kāi)發(fā)與運(yùn)維》的作者,付磊。

這個(gè)問(wèn)題我是在他的文章中看到的,感覺(jué)非常有趣,原來(lái) Redis 之前還存在這樣的 Bug 。隨后我又查閱了相關(guān)源碼,并對(duì)邏輯進(jìn)行了梳理,在這里才寫(xiě)成文章分享給大家。

雖然已在微信中親自答謝,但在這里再次表達(dá)對(duì)他的謝意~

最后,我們來(lái)看影響查詢結(jié)果的第 3 個(gè)因素:「機(jī)器時(shí)鐘」。

假設(shè)我們已規(guī)避了上面提到的版本 Bug,例如,我們使用 Redis 5.0 版本,在 slave 查詢一個(gè) key,還會(huì)和 master 結(jié)果不同嗎?

答案是,還是有可能會(huì)的。

這就與 master / slave 的機(jī)器時(shí)鐘有關(guān)了。

無(wú)論是 master 還是 slave,在判斷一個(gè) key 是否過(guò)期時(shí),都是基于「本機(jī)時(shí)鐘」來(lái)判斷的。

如果 slave 的機(jī)器時(shí)鐘比 master 走得「快」,那就會(huì)導(dǎo)致,即使這個(gè) key 還未過(guò)期,但以 slave 上視角來(lái)看,這個(gè) key 其實(shí)已經(jīng)過(guò)期了,那客戶端在 slave 上查詢時(shí),就會(huì)返回 NULL。

是不是很有意思?一個(gè)小小的過(guò)期 key,竟然藏匿這么多貓膩。

如果你也遇到了類似的情況,就可以通過(guò)上述步驟進(jìn)行排查,確認(rèn)是否踩到了這個(gè)坑。

3) 主從切換會(huì)導(dǎo)致緩存雪崩?

這個(gè)問(wèn)題是上一個(gè)問(wèn)題的延伸。

我們假設(shè),slave 的機(jī)器時(shí)鐘比 master 走得「快」,而且是「快很多」。

此時(shí),從 slave 角度來(lái)看,Redis 中的數(shù)據(jù)存在「大量過(guò)期」。

如果此時(shí)操作「主從切換」,把 slave 提升為新的 master。

它成為 master 后,就會(huì)開(kāi)始大量清理過(guò)期 key,此時(shí)就會(huì)導(dǎo)致以下結(jié)果:

master 大量清理過(guò)期 key,主線程發(fā)生阻塞,無(wú)法及時(shí)處理客戶端請(qǐng)求

Redis 中數(shù)據(jù)大量過(guò)期,引發(fā)緩存雪崩

你看,當(dāng) master / slave 機(jī)器時(shí)鐘嚴(yán)重不一致時(shí),對(duì)業(yè)務(wù)的影響非常大!

所以,如果你是 DBA 運(yùn)維,一定要保證主從庫(kù)的機(jī)器時(shí)鐘一致性,避免發(fā)生這些問(wèn)題。

4) master / slave 大量數(shù)據(jù)不一致?

還有一種場(chǎng)景,會(huì)導(dǎo)致 master / slave 的數(shù)據(jù)存在大量不一致。

這就涉及到 Redis 的 maxmemory 配置了。

Redis 的 maxmemory 可以控制整個(gè)實(shí)例的內(nèi)存使用上限,超過(guò)這個(gè)上限,并且配置了淘汰策略,那么實(shí)例就開(kāi)始淘汰數(shù)據(jù)。

但這里有個(gè)問(wèn)題:假設(shè) master / slave 配置的 maxmemory 不一樣,那此時(shí)就會(huì)發(fā)生數(shù)據(jù)不一致。

例如,master 配置的 maxmemory 為 5G,而 slave 的 maxmemory 為 3G,當(dāng) Redis 中的數(shù)據(jù)超過(guò) 3G 時(shí),slave 就會(huì)「提前」開(kāi)始淘汰數(shù)據(jù),此時(shí)主從庫(kù)數(shù)據(jù)發(fā)生不一致。

277aeb10-9878-11eb-8b86-12bb97331649.jpg

另外,盡管 master / slave 設(shè)置的 maxmemory 相同,如果你要調(diào)整它們的上限,也要格外注意,否則也會(huì)導(dǎo)致 slave 淘汰數(shù)據(jù):

調(diào)大 maxmemory 時(shí),先調(diào)整 slave,再調(diào)整 master

調(diào)小 maxmemory 時(shí),先調(diào)整 master,再調(diào)整 slave

以此方式操作,就避免了 slave 提前超過(guò) maxmemory 的問(wèn)題。

其實(shí),你可以思考一下,發(fā)生這些問(wèn)題的關(guān)鍵在哪?

其根本原因在于,slave 超過(guò) maxmemory 后,會(huì)「自行」淘汰數(shù)據(jù)。

如果不讓 slave 自己淘汰數(shù)據(jù),那這些問(wèn)題是不是都可以規(guī)避了?

沒(méi)錯(cuò)。

針對(duì)這個(gè)問(wèn)題,Redis 官方應(yīng)該也收到了很多用戶的反饋。在 Redis 5.0 版本,官方終于把這個(gè)問(wèn)題徹底解決了!

Redis 5.0 增加了一個(gè)配置項(xiàng):replica-ignore-maxmemory,默認(rèn) yes。

這個(gè)參數(shù)表示,盡管 slave 內(nèi)存超過(guò)了 maxmemory,也不會(huì)自行淘汰數(shù)據(jù)了!

這樣一來(lái),slave 永遠(yuǎn)會(huì)向 master 看齊,只會(huì)老老實(shí)實(shí)地復(fù)制 master 發(fā)送過(guò)來(lái)的數(shù)據(jù),不會(huì)自己再搞「小動(dòng)作」。

至此,master / slave 的數(shù)據(jù)就可以保證完全一致了!

如果你使用的恰好是 5.0 版本,就不用擔(dān)心這個(gè)問(wèn)題了。

5) slave 竟然會(huì)有內(nèi)存泄露問(wèn)題?

是的,你沒(méi)看錯(cuò)。

這是怎么發(fā)生的?我們具體來(lái)看一下。

當(dāng)你在使用 Redis 時(shí),符合以下場(chǎng)景,就會(huì)觸發(fā) slave 內(nèi)存泄露:

Redis 使用的是 4.0 以下版本

slave 配置項(xiàng)為 read-only=no(從庫(kù)可寫(xiě))

向 slave 寫(xiě)入了有過(guò)期時(shí)間的 key

這時(shí)的 slave 就會(huì)發(fā)生內(nèi)存泄露:slave 中的 key,即使到了過(guò)期時(shí)間,也不會(huì)自動(dòng)清理。

如果你不主動(dòng)刪除它,那這些 key 就會(huì)一直殘留在 slave 內(nèi)存中,消耗 slave 的內(nèi)存。

最麻煩的是,你使用命令查詢這些 key,卻還查不到任何結(jié)果!

這就 slave 「內(nèi)存泄露」問(wèn)題。

2784ee76-9878-11eb-8b86-12bb97331649.jpg

這其實(shí)也是 Redis 的一個(gè) Bug,Redis 4.0 才修復(fù)了這個(gè)問(wèn)題。

解決方案是,在可寫(xiě)的 slave 上,寫(xiě)入帶有過(guò)期時(shí)間 key 時(shí),slave 會(huì)「記錄」下來(lái)這些 key。

然后 slave 會(huì)定時(shí)掃描這些 key,如果到達(dá)過(guò)期時(shí)間,則清理之。

如果你的業(yè)務(wù)需要在 slave 上臨時(shí)存儲(chǔ)數(shù)據(jù),而且這些 key 也都設(shè)置了過(guò)期時(shí)間,那么就要注意這個(gè)問(wèn)題了。

你需要確認(rèn)你的 Redis 版本,如果是 4.0 以下版本,一定要避免踩這個(gè)坑。

其實(shí),最好的方案是,制定一個(gè) Redis 使用規(guī)范,slave 必須強(qiáng)制設(shè)置為 read-only,不允許寫(xiě),這樣不僅可以保證 master / slave 的數(shù)據(jù)一致性,還避免了 slave 內(nèi)存泄露問(wèn)題。

6) 為什么主從全量同步一直失?。?/p>

在主從全量同步時(shí),你可能會(huì)遇到同步失敗的問(wèn)題,具體場(chǎng)景如下:

slave 向 master 發(fā)起全量同步請(qǐng)求,master 生成 RDB 后發(fā)給 slave,slave 加載 RDB。

由于 RDB 數(shù)據(jù)太大,slave 加載耗時(shí)也會(huì)變得很長(zhǎng)。

此時(shí)你會(huì)發(fā)現(xiàn),slave 加載 RDB 還未完成,master 和 slave 的連接卻斷開(kāi)了,數(shù)據(jù)同步也失敗了。

之后你又會(huì)發(fā)現(xiàn),slave 又發(fā)起了全量同步,master 又生成 RDB 發(fā)送給 slave。

同樣地,slave 在加載 RDB 時(shí),master / slave 同步又失敗了,以此往復(fù)。

這是怎么回事?

其實(shí),這就是 Redis 的「復(fù)制風(fēng)暴」問(wèn)題。

什么是復(fù)制風(fēng)暴?

就像剛才描述的:主從全量同步失敗,又重新開(kāi)始同步,之后又同步失敗,以此往復(fù),惡性循環(huán),持續(xù)浪費(fèi)機(jī)器資源。

為什么會(huì)導(dǎo)致這種問(wèn)題呢?

如果你的 Redis 有以下特點(diǎn),就有可能發(fā)生這種問(wèn)題:

master 的實(shí)例數(shù)據(jù)過(guò)大,slave 在加載 RDB 時(shí)耗時(shí)太長(zhǎng)

復(fù)制緩沖區(qū)(slave client-output-buffer-limit)配置過(guò)小

master 寫(xiě)請(qǐng)求量很大

主從在全量同步數(shù)據(jù)時(shí),master 接收到的寫(xiě)請(qǐng)求,會(huì)先寫(xiě)到主從「復(fù)制緩沖區(qū)」中,這個(gè)緩沖區(qū)的「上限」是配置決定的。

當(dāng) slave 加載 RDB 太慢時(shí),就會(huì)導(dǎo)致 slave 無(wú)法及時(shí)讀取「復(fù)制緩沖區(qū)」的數(shù)據(jù),這就引發(fā)了復(fù)制緩沖區(qū)「溢出」。

為了避免內(nèi)存持續(xù)增長(zhǎng),此時(shí)的 master 會(huì)「強(qiáng)制」斷開(kāi) slave 的連接,這時(shí)全量同步就會(huì)失敗。

之后,同步失敗的 slave 又會(huì)「重新」發(fā)起全量同步,進(jìn)而又陷入上面描述的問(wèn)題中,以此往復(fù),惡性循環(huán),這就是所謂的「復(fù)制風(fēng)暴」。

如何解決這個(gè)問(wèn)題呢?我給你以下幾點(diǎn)建議:

Redis 實(shí)例不要太大,避免過(guò)大的 RDB

復(fù)制緩沖區(qū)配置的盡量大一些,給 slave 加載 RDB 留足時(shí)間,降低全量同步失敗的概率

如果你也踩到了這個(gè)坑,可以通過(guò)這個(gè)方案來(lái)解決。

總結(jié)

好了,總結(jié)一下,這篇文章我們主要講了 Redis 在「命令使用」、「數(shù)據(jù)持久化」、「主從同步」3 個(gè)方面可能存在的「坑」。

怎么樣?有沒(méi)有顛覆你的認(rèn)知呢?

這篇文章信息量還是比較大的,如果你現(xiàn)在的思維已經(jīng)有些「凌亂」了,別急,我也給你準(zhǔn)備好了思維導(dǎo)圖,方便你更好地理解和記憶。

27925516-9878-11eb-8b86-12bb97331649.png

希望你在使用 Redis 時(shí),可以提前規(guī)避這些坑,讓 Redis 更好地提供服務(wù)。

后記

最后,我想和你聊一聊在開(kāi)發(fā)過(guò)程中,關(guān)于踩坑的經(jīng)驗(yàn)和心得。

其實(shí),接觸任何一個(gè)新領(lǐng)域,都會(huì)經(jīng)歷陌生、熟悉、踩坑、吸收經(jīng)驗(yàn)、游刃有余這幾個(gè)階段。

那在踩坑這個(gè)階段,如何少踩坑?或者踩坑后如何高效率地排查問(wèn)題呢?

這里我總結(jié)出了 4 個(gè)方面,應(yīng)該可以幫助到你:

1) 多看官方文檔 + 配置文件的注釋

一定要多看官方文檔,以及配置文件的注釋說(shuō)明。其實(shí)很多可能存在風(fēng)險(xiǎn)的地方,優(yōu)秀的軟件都會(huì)在文檔和注釋里提示你的,認(rèn)真讀一讀,可以提前規(guī)避很多基礎(chǔ)問(wèn)題。

2) 不放過(guò)疑問(wèn)細(xì)節(jié),多思考為什么?

永遠(yuǎn)要保持好奇心。遇到問(wèn)題,掌握剝絲抽繭,逐步定位問(wèn)題的能力,時(shí)刻保持探尋事物問(wèn)題本質(zhì)的心態(tài)。

3) 敢于提出質(zhì)疑,源碼不會(huì)騙人

如果你覺(jué)得一個(gè)問(wèn)題很蹊蹺,可能是一個(gè) Bug,要敢于提出質(zhì)疑。

通過(guò)源碼尋找問(wèn)題的真相,這種方式要好過(guò)你看一百篇網(wǎng)上互相抄襲的文章(抄來(lái)抄去很有可能都是錯(cuò)的)。

4) 沒(méi)有完美的軟件,優(yōu)秀軟件都是一步步迭代出來(lái)的

任何優(yōu)秀的軟件,都是一步步迭代出來(lái)的。在迭代過(guò)程中,存在 Bug 很正常,我們需要抱著正確的心態(tài)去看待它。

這些經(jīng)驗(yàn)和心得,適用于學(xué)習(xí)任何領(lǐng)域,希望對(duì)你有所幫助。

原文標(biāo)題:Redis 會(huì)遇到的15個(gè)「坑」,你踩過(guò)幾個(gè)?

文章出處:【微信公眾號(hào):數(shù)據(jù)分析與開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 命令
    +關(guān)注

    關(guān)注

    5

    文章

    737

    瀏覽量

    22882
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    387

    瀏覽量

    11450

原文標(biāo)題:Redis 會(huì)遇到的15個(gè)「坑」,你踩過(guò)幾個(gè)?

文章出處:【微信號(hào):DBDevs,微信公眾號(hào):數(shù)據(jù)分析與開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    Redis集群部署配置詳解

    Redis集群是一種分布式Redis解決方案,通過(guò)數(shù)據(jù)分片和主從復(fù)制實(shí)現(xiàn)高可用性和橫向擴(kuò)展。集群將整個(gè)數(shù)據(jù)集分割成16384個(gè)哈希槽(hash slots),每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分槽位。
    的頭像 發(fā)表于 07-17 11:04 ?127次閱讀

    Redis集群部署與性能優(yōu)化實(shí)戰(zhàn)

    Redis作為高性能的內(nèi)存數(shù)據(jù)庫(kù),在現(xiàn)代互聯(lián)網(wǎng)架構(gòu)中扮演著關(guān)鍵角色。作為運(yùn)維工程師,掌握Redis的部署、配置和優(yōu)化技能至關(guān)重要。本文將從實(shí)戰(zhàn)角度出發(fā),詳細(xì)介紹Redis集群的搭建、性能優(yōu)化以及監(jiān)控運(yùn)維的核心技術(shù)。
    的頭像 發(fā)表于 07-08 17:56 ?239次閱讀

    【經(jīng)驗(yàn)分享】在Omni3576上編譯Redis-8.0.2源碼,并安裝及性能測(cè)試

    本文首先介紹Redis是什么,然后介紹如何在Omni3576上編譯Redis-8.0.2源碼,以及從源碼編譯、安裝Redis,最后介紹如何在Omni3576上運(yùn)行Redis性能測(cè)試,并
    的頭像 發(fā)表于 06-05 08:05 ?298次閱讀
    【經(jīng)驗(yàn)分享】在Omni3576上編譯<b class='flag-5'>Redis</b>-8.0.2源碼,并安裝及性能測(cè)試

    【幸狐Omni3576邊緣計(jì)算套件試用體驗(yàn)】Redis最新8.0.2版本源碼安裝及性能測(cè)試

    本文首先介紹Redis是什么,然后介紹如何在Omni3576上編譯Redis-8.0.2源碼,以及從源碼編譯、安裝Redis,最后介紹如何在Omni3576上運(yùn)行Redis性能測(cè)試,并
    發(fā)表于 06-03 01:28

    Redis 再次開(kāi)源!

    “ ?Redis 現(xiàn)已采用 AGPLv3 開(kāi)源許可證。? ” Redis CEO 的 Blog 以下是 Redis CEO Rowan Trollope 的 Blog: 像 AWS 和 GCP 這樣
    的頭像 發(fā)表于 05-06 18:26 ?406次閱讀

    Modbus TCP通信的那些!你遇到過(guò)幾個(gè)?

    凌晨三點(diǎn),產(chǎn)線驟停!觸摸屏瘋狂報(bào)通訊超時(shí),老板奪命連環(huán)Call轟炸,而你盯著PLC的Error燈狂閃、儀表數(shù)據(jù)集體躺平——Modbus TCP的,誰(shuí)踩誰(shuí)懂! 別慌!這篇Modbus TCP常見(jiàn)問(wèn)題
    的頭像 發(fā)表于 04-16 17:17 ?543次閱讀
    Modbus TCP通信的那些<b class='flag-5'>坑</b>!你<b class='flag-5'>遇到</b>過(guò)幾個(gè)?

    redis三種集群方案詳解

    Redis中提供的集群方案總共有三種(一般一個(gè)redis節(jié)點(diǎn)不超過(guò)10G內(nèi)存)。
    的頭像 發(fā)表于 03-31 10:46 ?730次閱讀
    <b class='flag-5'>redis</b>三種集群方案詳解

    Redis實(shí)戰(zhàn)筆記

    在目前的技術(shù)選型中,Redis 儼然已經(jīng)成為了系統(tǒng)高性能緩存方案的事實(shí)標(biāo)準(zhǔn),因此現(xiàn)在?Redis 也成為了后端開(kāi)發(fā)的基本技能樹(shù)之一。 ? 基于上述情況,今天給大家分享一份?杰哥?親筆撰寫(xiě)的內(nèi)部
    的頭像 發(fā)表于 02-09 09:12 ?395次閱讀
    <b class='flag-5'>Redis</b>實(shí)戰(zhàn)筆記

    華為云 Flexus X 加速 Redis 案例實(shí)踐與詳解

    Redis 加速鏡像,更是為開(kāi)發(fā)者提供了極大的便利。本文將詳細(xì)介紹如何利用華為云 Flexus X 實(shí)例自帶的 Redis 鏡像,快速部署并配置 Redis,以及通過(guò)實(shí)際案例展示其便捷性和高效性。 一、華為云 Flexus
    的頭像 發(fā)表于 01-23 17:52 ?337次閱讀
    華為云 Flexus X 加速 <b class='flag-5'>Redis</b> 案例實(shí)踐與詳解

    Redis Cluster之故障轉(zhuǎn)移

    1. Redis Cluster 簡(jiǎn)介 Redis Cluster 是 Redis 官方提供的 Redis 集群功能。 為什么要實(shí)現(xiàn) Redis
    的頭像 發(fā)表于 01-20 09:21 ?896次閱讀
    <b class='flag-5'>Redis</b> Cluster之故障轉(zhuǎn)移

    云服務(wù)器 Flexus X 實(shí)例,Docker 集成搭建 Redis 集群

    Redis 集群是一種分布式的 Redis 解決方案,能夠在多個(gè)節(jié)點(diǎn)之間分片存儲(chǔ)數(shù)據(jù),實(shí)現(xiàn)水平擴(kuò)展和高可用性。與傳統(tǒng)的主從架構(gòu)不同,Redis 集群支持?jǐn)?shù)據(jù)自動(dòng)分片、主節(jié)點(diǎn)故障自動(dòng)切換,并可以在多臺(tái)
    的頭像 發(fā)表于 01-13 13:37 ?382次閱讀
    云服務(wù)器 Flexus X 實(shí)例,Docker 集成搭建 <b class='flag-5'>Redis</b> 集群

    OTDR測(cè)試中常遇到的問(wèn)題及解決

    OTDR(光時(shí)域反射儀)是一種用于測(cè)量光纖鏈路損耗和識(shí)別光纖故障點(diǎn)的測(cè)試設(shè)備。在OTDR測(cè)試過(guò)程中,可能會(huì)遇到各種問(wèn)題,以下是一些常見(jiàn)問(wèn)題及其解決方案的概述: 1. 光纖端面反射 問(wèn)題描述: 當(dāng)
    的頭像 發(fā)表于 12-31 09:34 ?1268次閱讀

    華為云Flexus X實(shí)例,Redis性能加速評(píng)測(cè)及對(duì)比

    隨著云計(jì)算技術(shù)的飛速發(fā)展,Redis 作為一種高性能的內(nèi)存數(shù)據(jù)庫(kù),在各種應(yīng)用場(chǎng)景中發(fā)揮著越來(lái)越重要的作用。為了滿足不同用戶對(duì) Redis 性能的高要求,華為云推出了 Flexus X 實(shí)例,并提供了
    的頭像 發(fā)表于 12-29 15:47 ?499次閱讀
    華為云Flexus X實(shí)例,<b class='flag-5'>Redis</b>性能加速評(píng)測(cè)及對(duì)比

    華為云 Flexus X 輕松實(shí)現(xiàn) Redis 一主多從高效部署

    前言 ????????華為云 Flexus?X 是一款專為高性能計(jì)算設(shè)計(jì)的云服務(wù)器實(shí)例,其搭載的 X-Turbo 加速技術(shù)和智能應(yīng)用調(diào)優(yōu)算法,能夠大幅提升 Redis 的處理能力和響應(yīng)速度。此外
    的頭像 發(fā)表于 12-27 13:45 ?493次閱讀
    華為云 Flexus X 輕松實(shí)現(xiàn) <b class='flag-5'>Redis</b> 一主多從高效部署

    Redis緩存與Memcached的比較

    Redis和Memcached都是廣泛使用的內(nèi)存數(shù)據(jù)存儲(chǔ)系統(tǒng),它們主要用于提高應(yīng)用程序的性能,通過(guò)減少對(duì)數(shù)據(jù)庫(kù)的直接訪問(wèn)來(lái)加速數(shù)據(jù)檢索。以下是對(duì)Redis和Memcached的比較,涵蓋了它們的一些
    的頭像 發(fā)表于 12-18 09:33 ?596次閱讀