讀完這篇文章,就基本搞定了Redis數(shù)據(jù)庫(kù)
另外,Redis 也經(jīng)常用來(lái)做分布式鎖。Redis 提供了多種數(shù)據(jù)類(lèi)型來(lái)支持不同的業(yè)務(wù)場(chǎng)景。
除此之外,Redis 支持事務(wù) 、持久化、LUA 腳本、LRU 驅(qū)動(dòng)事件、多種集群方案。
本文將從以下幾個(gè)方面全面解讀 Redis:
- 為什么要用 Redis / 為什么要用緩存
- 為什么要用 Redis 而不用 map/guava 做緩存
- Redis 和 Memcached 的區(qū)別
- Redis 常見(jiàn)數(shù)據(jù)結(jié)構(gòu)以及使用場(chǎng)景分析
- Redis 設(shè)置過(guò)期時(shí)間
- Redis 內(nèi)存淘汰機(jī)制
- Redis 持久化機(jī)制(怎么保證 Redis 掛掉之后再重啟數(shù)據(jù)可以進(jìn)行恢復(fù))
- Redis 事務(wù)
- 緩存雪崩和緩存穿透問(wèn)題解決方案
- 如何解決 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問(wèn)題
- 如何保證緩存與數(shù)據(jù)庫(kù)雙寫(xiě)時(shí)的數(shù)據(jù)一致性
為什么要用 Redis / 為什么要用緩存?
主要從“高性能”和“高并發(fā)”這兩點(diǎn)來(lái)看待這個(gè)問(wèn)題。
高性能
假如用戶第一次訪問(wèn)數(shù)據(jù)庫(kù)中的某些數(shù)據(jù)。這個(gè)過(guò)程會(huì)比較慢,因?yàn)槭菑挠脖P(pán)上讀取的。
將該用戶訪問(wèn)的數(shù)據(jù)存在緩存中,這樣下一次再訪問(wèn)這些數(shù)據(jù)的時(shí)候就可以直接從緩存中獲取了。
操作緩存就是直接操作內(nèi)存,所以速度相當(dāng)快。如果數(shù)據(jù)庫(kù)中的對(duì)應(yīng)數(shù)據(jù)改變了之后,同步改變緩存中相應(yīng)的數(shù)據(jù)即可!
高并發(fā)

直接操作緩存能夠承受的請(qǐng)求是遠(yuǎn)遠(yuǎn)大于直接訪問(wèn)數(shù)據(jù)庫(kù)的,所以我們可以考慮把數(shù)據(jù)庫(kù)中的部分?jǐn)?shù)據(jù)轉(zhuǎn)移到緩存中去,這樣用戶的一部分請(qǐng)求會(huì)直接到緩存這里而不用經(jīng)過(guò)數(shù)據(jù)庫(kù)。
為什么要用 Redis 而不用 map/guava 做緩存
緩存分為本地緩存和分布式緩存。以 Java 為例,使用自帶的 map 或者 guava 實(shí)現(xiàn)的是本地緩存,最主要的特點(diǎn)是輕量以及快速,生命周期隨著 JVM 的銷(xiāo)毀而結(jié)束。
并且在多實(shí)例的情況下,每個(gè)實(shí)例都需要各自保存一份緩存,緩存不具有一致性。
使用 Redis 或 Memcached 之類(lèi)的稱為分布式緩存,在多實(shí)例的情況下,各實(shí)例共用一份緩存數(shù)據(jù),緩存具有一致性。
缺點(diǎn)是需要保持 Redis 或 Memcached 服務(wù)的高可用,整個(gè)程序架構(gòu)上較為復(fù)雜。
Redis 和 Memcached 的區(qū)別
現(xiàn)在公司一般都是用 Redis 來(lái)實(shí)現(xiàn)緩存,而且 Redis 自身也越來(lái)越強(qiáng)大了!
對(duì)于 Redis 和 Memcached 我總結(jié)了下面四點(diǎn):
- Redis 支持更豐富的數(shù)據(jù)類(lèi)型(支持更復(fù)雜的應(yīng)用場(chǎng)景):Redis 不僅僅支持簡(jiǎn)單的 K/V 類(lèi)型的數(shù)據(jù),同時(shí)還提供 list、set、zset、hash 等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。Memcache 支持簡(jiǎn)單的數(shù)據(jù)類(lèi)型 String。
- Redis 支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保持在磁盤(pán)中,重啟的時(shí)候可以再次加載進(jìn)行使用,而 Memecache 把數(shù)據(jù)全部存在內(nèi)存之中。
- 集群模式:Memcached 沒(méi)有原生的集群模式,需要依靠客戶端來(lái)實(shí)現(xiàn)往集群中分片寫(xiě)入數(shù)據(jù);但是 Redis 目前是原生支持 Cluster 模式的。
- Memcached 是多線程,非阻塞 IO 復(fù)用的網(wǎng)絡(luò)模型;Redis 使用單線程的多路 IO 復(fù)用模型。
來(lái)自網(wǎng)絡(luò)上的一張對(duì)比圖,這里分享給大家:
Redis 常見(jiàn)數(shù)據(jù)結(jié)構(gòu)以及使用場(chǎng)景分析
String
常用命令:set、get、decr、incr、mget 等。
String 數(shù)據(jù)結(jié)構(gòu)是簡(jiǎn)單的 Key-Value 類(lèi)型,Value 其實(shí)不僅可以是 String,也可以是數(shù)字。常規(guī) Key-Value 緩存應(yīng)用;常規(guī)計(jì)數(shù):微博數(shù),粉絲數(shù)等。
Hash
常用命令: hget、hset、hgetall 等。
Hash 是一個(gè) String 類(lèi)型的 Field 和 Value 的映射表,Hash 特別適合用于存儲(chǔ)對(duì)象。
后續(xù)操作的時(shí)候,你可以直接僅僅修改這個(gè)對(duì)象中的某個(gè)字段的值。比如我們可以 Hash 數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)用戶信息,商品信息等等。
比如下面我就用 Hash 類(lèi)型存放了我本人的一些信息:
- key=JavaUser293847
- value={
- “id”: 1,
- “name”: “SnailClimb”,
- “age”: 22,
- “location”: “Wuhan, Hubei”
- }
List
常用命令:lpush、rpush、lpop、rpop、lrange 等。
List 就是鏈表,Redis List 的應(yīng)用場(chǎng)景非常多,也是 Redis 最重要的數(shù)據(jù)結(jié)構(gòu)之一。
比如微博的關(guān)注列表,粉絲列表,消息列表等功能都可以用 Redis 的 List 結(jié)構(gòu)來(lái)實(shí)現(xiàn)。
Redis List 的實(shí)現(xiàn)為一個(gè)雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過(guò)帶來(lái)了部分額外的內(nèi)存開(kāi)銷(xiāo)。
另外可以通過(guò) lrange 命令,就是從某個(gè)元素開(kāi)始讀取多少個(gè)元素,可以基于 List 實(shí)現(xiàn)分頁(yè)查詢。
這是很棒的一個(gè)功能,基于 Redis 實(shí)現(xiàn)簡(jiǎn)單的高性能分頁(yè),可以做類(lèi)似微博那種下拉不斷分頁(yè)的東西(一頁(yè)一頁(yè)的往下走),性能高。
Set
常用命令:sadd、spop、smembers、sunion 等。
Set 對(duì)外提供的功能與 List 類(lèi)似是一個(gè)列表的功能,特殊之處在于 Set 是可以自動(dòng)排重的。
當(dāng)你需要存儲(chǔ)一個(gè)列表數(shù)據(jù),又不希望出現(xiàn)重復(fù)數(shù)據(jù)時(shí),Set 是一個(gè)很好的選擇。
并且 Set 提供了判斷某個(gè)成員是否在一個(gè) Set 集合內(nèi)的重要接口,這個(gè)也是 List 所不能提供的。你可以基于 Set 輕易實(shí)現(xiàn)交集、并集、差集的操作。
比如:在微博應(yīng)用中,可以將一個(gè)用戶所有的關(guān)注人存在一個(gè)集合中,將其所有粉絲存在一個(gè)集合。Redis 可以非常方便的實(shí)現(xiàn)如共同關(guān)注、共同粉絲、共同喜好等功能。
這個(gè)過(guò)程也就是求交集的過(guò)程,具體命令如下:
- sinterstore key1 key2 key3 將交集存在key1內(nèi)
Sorted Set
常用命令:zadd、zrange、zrem、zcard 等。
和 Set 相比,Sorted Set 增加了一個(gè)權(quán)重參數(shù) Score,使得集合中的元素能夠按 Score 進(jìn)行有序排列。
舉例:在直播系統(tǒng)中,實(shí)時(shí)排行信息包含直播間在線用戶列表,各種禮物排行榜,彈幕消息(可以理解為按消息維度的消息排行榜)等信息,適合使用 Redis 中的 Sorted Set 結(jié)構(gòu)進(jìn)行存儲(chǔ)。
Redis 設(shè)置過(guò)期時(shí)間
Redis 中有個(gè)設(shè)置過(guò)期時(shí)間的功能,即對(duì)存儲(chǔ)在 Redis 數(shù)據(jù)庫(kù)中的值可以設(shè)置一個(gè)過(guò)期時(shí)間。作為一個(gè)緩存數(shù)據(jù)庫(kù),這是非常實(shí)用的。
如我們一般項(xiàng)目中的 Token 或者一些登錄信息,尤其是短信驗(yàn)證碼都是有時(shí)間限制的,按照傳統(tǒng)的數(shù)據(jù)庫(kù)處理方式,一般都是自己判斷過(guò)期,這樣無(wú)疑會(huì)嚴(yán)重影響項(xiàng)目性能。
我們 Set Key 的時(shí)候,都可以給一個(gè) Expire Time,就是過(guò)期時(shí)間,通過(guò)過(guò)期時(shí)間我們可以指定這個(gè) Key 可以存活的時(shí)間。
如果你設(shè)置了一批 Key 只能存活 1 個(gè)小時(shí),那么接下來(lái) 1 小時(shí)后,Redis 是怎么對(duì)這批 Key 進(jìn)行刪除的?
答案是:定期刪除+惰性刪除。通過(guò)名字大概就能猜出這兩個(gè)刪除方式的意思了:
- 定期刪除:Redis 默認(rèn)是每隔 100ms 就隨機(jī)抽取一些設(shè)置了過(guò)期時(shí)間的 Key,檢查其是否過(guò)期,如果過(guò)期就刪除。
注意這里是隨機(jī)抽取的。為什么要隨機(jī)呢?你想一想假如 Redis 存了幾十萬(wàn)個(gè) Key ,每隔 100ms 就遍歷所有的設(shè)置過(guò)期時(shí)間的 Key 的話,就會(huì)給 CPU 帶來(lái)很大的負(fù)載!
- 惰性刪除 :定期刪除可能會(huì)導(dǎo)致很多過(guò)期 Key 到了時(shí)間并沒(méi)有被刪除掉。所以就有了惰性刪除。
假如你的過(guò)期 Key,靠定期刪除沒(méi)有被刪除掉,還停留在內(nèi)存里,除非你的系統(tǒng)去查一下那個(gè) Key,才會(huì)被 Redis 給刪除掉。這就是所謂的惰性刪除,也是夠懶的哈!
但是僅僅通過(guò)設(shè)置過(guò)期時(shí)間還是有問(wèn)題的。我們想一下:如果定期刪除漏掉了很多過(guò)期 Key,然后你也沒(méi)及時(shí)去查,也就沒(méi)走惰性刪除,此時(shí)會(huì)怎么樣?
如果大量過(guò)期 Key 堆積在內(nèi)存里,導(dǎo)致 Redis 內(nèi)存塊耗盡了。怎么解決這個(gè)問(wèn)題呢?
Redis 內(nèi)存淘汰機(jī)制
MySQL 里有 2000w 數(shù)據(jù),Redis 中只存 20w 的數(shù)據(jù),如何保證 Redis 中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)?
Redis 配置文件 redis.conf 中有相關(guān)注釋,我這里就不貼了,大家可以自行查閱或者通過(guò)這個(gè)網(wǎng)址查看:http://download.redis.io/redis-stable/redis.conf
Redis 提供 6 種數(shù)據(jù)淘汰策略:
- volatile-lru:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰。
- volatile-ttl:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過(guò)期的數(shù)據(jù)淘汰。
- volatile-random:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰。
- allkeys-lru:當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),在鍵空間中,移除最近最少使用的key(這個(gè)是最常用的)。
- allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰。
- no-enviction:禁止驅(qū)逐數(shù)據(jù),也就是說(shuō)當(dāng)內(nèi)存不足以容納新寫(xiě)入數(shù)據(jù)時(shí),新寫(xiě)入操作會(huì)報(bào)錯(cuò)。這個(gè)應(yīng)該沒(méi)人使用吧!
Redis 持久化機(jī)制
怎么保證 Redis 掛掉之后再重啟數(shù)據(jù)可以進(jìn)行恢復(fù)?很多時(shí)候我們需要持久化數(shù)據(jù)也就是將內(nèi)存中的數(shù)據(jù)寫(xiě)入到硬盤(pán)里面。
大部分原因是為了之后重用數(shù)據(jù)(比如重啟機(jī)器、機(jī)器故障之后恢復(fù)數(shù)據(jù)),或者是為了防止系統(tǒng)故障而將數(shù)據(jù)備份到一個(gè)遠(yuǎn)程位置。
Redis 不同于 Memcached 的很重要一點(diǎn)就是,Redis 支持持久化,而且支持兩種不同的持久化操作。
Redis 的一種持久化方式叫快照(snapshotting,RDB),另一種方式是只追加文件(append-only file,AOF)。
這兩種方法各有千秋,下面我會(huì)詳細(xì)講這兩種持久化方法是什么,怎么用,如何選擇適合自己的持久化方法。
快照(snapshotting)持久化(RDB)
Redis 可以通過(guò)創(chuàng)建快照來(lái)獲得存儲(chǔ)在內(nèi)存里面的數(shù)據(jù)在某個(gè)時(shí)間點(diǎn)上的副本。
Redis 創(chuàng)建快照之后,可以對(duì)快照進(jìn)行備份,可以將快照復(fù)制到其他服務(wù)器從而創(chuàng)建具有相同數(shù)據(jù)的服務(wù)器副本(Redis 主從結(jié)構(gòu),主要用來(lái)提高 Redis 性能),還可以將快照留在原地以便重啟服務(wù)器的時(shí)候使用。
快照持久化是 Redis 默認(rèn)采用的持久化方式,在 redis.conf 配置文件中默認(rèn)有此下配置:
- save 900 1 #在900秒(15分鐘)之后,如果至少有1個(gè)key發(fā)生變化,Redis就會(huì)自動(dòng)觸發(fā)BGSAVE命令創(chuàng)建快照。
- save 300 10 #在300秒(5分鐘)之后,如果至少有10個(gè)key發(fā)生變化,Redis就會(huì)自動(dòng)觸發(fā)BGSAVE命令創(chuàng)建快照。
- save 60 10000 #在60秒(1分鐘)之后,如果至少有10000個(gè)key發(fā)生變化,Redis就會(huì)自動(dòng)觸發(fā)BGSAVE命令創(chuàng)建快照。
AOF(append-only file)持久化
與快照持久化相比,AOF 持久化的實(shí)時(shí)性更好,因此已成為主流的持久化方案。
默認(rèn)情況下 Redis 沒(méi)有開(kāi)啟 AOF(append only file)方式的持久化,可以通過(guò) appendonly 參數(shù)開(kāi)啟:
- appendonly yes
開(kāi)啟 AOF 持久化后每執(zhí)行一條會(huì)更改 Redis 中的數(shù)據(jù)的命令,Redis 就會(huì)將該命令寫(xiě)入硬盤(pán)中的 AOF 文件。
AOF 文件的保存位置和 RDB 文件的位置相同,都是通過(guò) dir 參數(shù)設(shè)置的,默認(rèn)的文件名是 appendonly.aof。
在 Redis 的配置文件中存在三種不同的 AOF 持久化方式,它們分別是:
- appendfsync always #每次有數(shù)據(jù)修改發(fā)生時(shí)都會(huì)寫(xiě)入AOF文件,這樣會(huì)嚴(yán)重降低Redis的速度
- appendfsync everysec #每秒鐘同步一次,顯示地將多個(gè)寫(xiě)命令同步到硬盤(pán)
- appendfsync no #讓操作系統(tǒng)決定何時(shí)進(jìn)行同步
為了兼顧數(shù)據(jù)和寫(xiě)入性能,用戶可以考慮 appendfsync everysec 選項(xiàng) ,讓 Redis 每秒同步一次 AOF 文件,Redis 性能幾乎沒(méi)受到任何影響。
而且這樣即使出現(xiàn)系統(tǒng)崩潰,用戶最多只會(huì)丟失一秒之內(nèi)產(chǎn)生的數(shù)據(jù)。當(dāng)硬盤(pán)忙于執(zhí)行寫(xiě)入操作的時(shí)候,Redis 還會(huì)優(yōu)雅的放慢自己的速度以便適應(yīng)硬盤(pán)的最大寫(xiě)入速度。
Redis 4.0 對(duì)于持久化機(jī)制的優(yōu)化
Redis 4.0 開(kāi)始支持 RDB 和 AOF 的混合持久化(默認(rèn)關(guān)閉,可以通過(guò)配置項(xiàng) aof-use-rdb-preamble 開(kāi)啟)。
如果把混合持久化打開(kāi),AOF 重寫(xiě)的時(shí)候就直接把 RDB 的內(nèi)容寫(xiě)到 AOF 文件開(kāi)頭。
這樣做的好處是可以結(jié)合 RDB 和 AOF 的優(yōu)點(diǎn), 快速加載同時(shí)避免丟失過(guò)多的數(shù)據(jù)。
當(dāng)然缺點(diǎn)也是有的,AOF 里面的 RDB 部分是壓縮格式不再是 AOF 格式,可讀性較差。
補(bǔ)充內(nèi)容:AOF 重寫(xiě)
AOF 重寫(xiě)可以產(chǎn)生一個(gè)新的 AOF 文件,這個(gè)新的 AOF 文件和原有的 AOF 文件所保存的數(shù)據(jù)庫(kù)狀態(tài)一樣,但體積更小。
AOF 重寫(xiě)是一個(gè)有歧義的名字,該功能是通過(guò)讀取數(shù)據(jù)庫(kù)中的鍵值對(duì)來(lái)實(shí)現(xiàn)的,程序無(wú)須對(duì)現(xiàn)有 AOF 文件進(jìn)行任伺讀入、分析或者寫(xiě)入操作。
在執(zhí)行 BGREWRITEAOF 命令時(shí),Redis 服務(wù)器會(huì)維護(hù)一個(gè) AOF 重寫(xiě)緩沖區(qū),該緩沖區(qū)會(huì)在子進(jìn)程創(chuàng)建新 AOF 文件期間,記錄服務(wù)器執(zhí)行的所有寫(xiě)命令。
當(dāng)子進(jìn)程完成創(chuàng)建新 AOF 文件的工作之后,服務(wù)器會(huì)將重寫(xiě)緩沖區(qū)中的所有內(nèi)容追加到新 AOF 文件的末尾,使得新舊兩個(gè) AOF 文件所保存的數(shù)據(jù)庫(kù)狀態(tài)一致。
最后,服務(wù)器用新的 AOF 文件替換舊的 AOF 文件,以此來(lái)完成 AOF 文件重寫(xiě)操作。
Redis 事務(wù)
Redis 通過(guò) MULTI、EXEC、WATCH 等命令來(lái)實(shí)現(xiàn)事務(wù)(transaction)功能。
事務(wù)提供了一種將多個(gè)命令請(qǐng)求打包,然后一次性、按順序地執(zhí)行多個(gè)命令的機(jī)制。
并且在事務(wù)執(zhí)行期間,服務(wù)器不會(huì)中斷事務(wù)而改去執(zhí)行其他客戶端的命令請(qǐng)求,它會(huì)將事務(wù)中的所有命令都執(zhí)行完畢,然后才去處理其他客戶端的命令請(qǐng)求。
在傳統(tǒng)的關(guān)系式數(shù)據(jù)庫(kù)中,常常用 ACID 性質(zhì)來(lái)檢驗(yàn)事務(wù)功能的可靠性和安全性。
在 Redis 中,事務(wù)總是具有原子性(Atomicity)、一致性(Consistency)和隔離性(Isolation),并且當(dāng) Redis 運(yùn)行在某種特定的持久化模式下時(shí),事務(wù)也具有持久性(Durability)。
緩存雪崩和緩存穿透問(wèn)題解決方案
緩存雪崩
簡(jiǎn)介:緩存同一時(shí)間大面積的失效,所以,后面的請(qǐng)求都會(huì)落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉。
解決辦法:
- 事前:盡量保證整個(gè) Redis 集群的高可用性,發(fā)現(xiàn)機(jī)器宕機(jī)盡快補(bǔ)上。選擇合適的內(nèi)存淘汰策略。
- 事中:本地 Ehcache 緩存 + Hystrix 限流&降級(jí),避免 MySQL 崩掉。
- 事后:利用 Redis 持久化機(jī)制保存的數(shù)據(jù)盡快恢復(fù)緩存。
緩存穿透
簡(jiǎn)介:一般是黑客故意去請(qǐng)求緩存中不存在的數(shù)據(jù),導(dǎo)致所有的請(qǐng)求都落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉。
解決辦法:有很多種方法可以有效地解決緩存穿透問(wèn)題,最常見(jiàn)的則是采用布隆過(guò)濾器,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的 bitmap 中。
一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè) bitmap 攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力。
另外也有一個(gè)更為簡(jiǎn)單粗暴的方法(我們采用的就是這種),如果一個(gè)查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過(guò)期時(shí)間會(huì)很短,最長(zhǎng)不超過(guò)五分鐘。
如何解決 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問(wèn)題
所謂 Redis 的并發(fā)競(jìng)爭(zhēng) Key 的問(wèn)題也就是多個(gè)系統(tǒng)同時(shí)對(duì)一個(gè) Key 進(jìn)行操作,但是最后執(zhí)行的順序和我們期望的順序不同,這樣也就導(dǎo)致了結(jié)果的不同!
推薦一種方案:分布式鎖(ZooKeeper 和 Redis 都可以實(shí)現(xiàn)分布式鎖)。(如果不存在 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問(wèn)題,不要使用分布式鎖,這樣會(huì)影響性能)
基于 ZooKeeper 臨時(shí)有序節(jié)點(diǎn)可以實(shí)現(xiàn)的分布式鎖。大致思想為:每個(gè)客戶端對(duì)某個(gè)方法加鎖時(shí),在 ZooKeeper 上的與該方法對(duì)應(yīng)的指定節(jié)點(diǎn)的目錄下,生成一個(gè)唯一的瞬時(shí)有序節(jié)點(diǎn)。
判斷是否獲取鎖的方式很簡(jiǎn)單,只需要判斷有序節(jié)點(diǎn)中序號(hào)最小的一個(gè)。 當(dāng)釋放鎖的時(shí)候,只需將這個(gè)瞬時(shí)節(jié)點(diǎn)刪除即可。
同時(shí),其可以避免服務(wù)宕機(jī)導(dǎo)致的鎖無(wú)法釋放,而產(chǎn)生的死鎖問(wèn)題。完成業(yè)務(wù)流程后,刪除對(duì)應(yīng)的子節(jié)點(diǎn)釋放鎖。
在實(shí)踐中,當(dāng)然是以可靠性為主。所以首推 ZooKeeper。
如何保證緩存與數(shù)據(jù)庫(kù)雙寫(xiě)時(shí)的數(shù)據(jù)一致性
你只要用緩存,就可能會(huì)涉及到緩存與數(shù)據(jù)庫(kù)雙存儲(chǔ)雙寫(xiě),你只要是雙寫(xiě),就一定會(huì)有數(shù)據(jù)一致性的問(wèn)題,那么你如何解決一致性問(wèn)題?
一般來(lái)說(shuō),就是如果你的系統(tǒng)不是嚴(yán)格要求緩存+數(shù)據(jù)庫(kù)必須一致性的話,緩存可以稍微的跟數(shù)據(jù)庫(kù)偶爾有不一致的情況。
最好不要做這個(gè)方案,讀請(qǐng)求和寫(xiě)請(qǐng)求串行化,串到一個(gè)內(nèi)存隊(duì)列里去,這樣就可以保證一定不會(huì)出現(xiàn)不一致的情況。
串行化之后,就會(huì)導(dǎo)致系統(tǒng)的吞吐量會(huì)大幅度的降低,用比正常情況下多幾倍的機(jī)器去支撐線上的一個(gè)請(qǐng)求。
參考文章:
- https://segmentfault.com/q/1010000009106416
- Redis設(shè)計(jì)與實(shí)現(xiàn)(第二版)
- https://www.jianshu.com/p/8bddd381de06
- https://blog.csdn.net/zeb_perfect/article/details/54135506
- Java工程師面試突擊第1季(可能是史上最好的Java面試突擊課程)-中華石杉老師。鏈接: https://pan.baidu.com/s/18pp6g1xKVGCfUATf_nMrOA,密碼:5i58
福利來(lái)啦
請(qǐng)結(jié)合自身情況談?wù)勥\(yùn)用 Redis 中的難點(diǎn)。掃描下方二維碼,關(guān)注51CTO技術(shù)棧公眾號(hào)。歡迎在技術(shù)棧微信公眾號(hào)留言探討。小編將選出留言最精彩的 10 名網(wǎng)友,送出《PHP 高性能開(kāi)發(fā):基礎(chǔ)、框架與項(xiàng)目實(shí)戰(zhàn)》圖書(shū)一本~活動(dòng)截止時(shí)間 10 月 4 日十二時(shí)整,特別鳴謝機(jī)械工業(yè)出版社為本次活動(dòng)提供的圖書(shū)贊助。等不及送書(shū)的小伙伴,可以點(diǎn)擊閱讀原文直接購(gòu)買(mǎi)。
書(shū)籍簡(jiǎn)介
本書(shū)分為 3 篇:第 1 篇基礎(chǔ)入門(mén)篇,包括 PHP 快速入門(mén)、虛擬機(jī)與個(gè)性化開(kāi)發(fā)環(huán)境搭建、Git 版本控制、高效團(tuán)隊(duì)合作、PHP Storm 技巧、Composer 包管理工具等內(nèi)容。第 2 篇框架進(jìn)階篇,分別介紹了前端框架 Bootstrap 和后端框架 ThinkPHP5,幫助開(kāi)發(fā)者掌握快速開(kāi)發(fā)項(xiàng)目的方法。第 3 篇項(xiàng)目實(shí)戰(zhàn)篇,帶領(lǐng)開(kāi)發(fā)者完成了一個(gè)基本的內(nèi)容管理框架,并在此基礎(chǔ)上實(shí)現(xiàn)了計(jì)劃任務(wù)的可視化管理和基于 Redis 隊(duì)列的商城搶購(gòu)系統(tǒng)。