redis
什么是redis
全稱remote dictionary server, 是一個(gè)基于內(nèi)存的高性能key-value數(shù)據(jù)庫
有什么優(yōu)點(diǎn)
- 1.速度快:數(shù)據(jù)存在內(nèi)存中
- 2.支持豐富數(shù)據(jù)類型:支持 String 全释,List,Set屉来,Sorted Set圈膏,Hash 五種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),單個(gè) Value 的最大限制是 1GB,還提供 Bitmap,HyperLogLog,GEO等高級的數(shù)據(jù)結(jié)構(gòu).
- 3.豐富的特性:訂閱發(fā)布 Pub / Sub 功能他去、Key 過期策略浮还、事務(wù)、支持多個(gè) DB拜鹤、計(jì)數(shù)
- 4.持久化存儲:提供RDB和AOF兩種數(shù)據(jù)的持久化存儲方案
- 5.高可用:內(nèi)置 Redis Sentinel 框冀,提供高可用方案,實(shí)現(xiàn)主從故障自動(dòng)轉(zhuǎn)移敏簿。內(nèi)置 Redis Cluster 明也,提供集群方案,實(shí)現(xiàn)基于槽的分片方案惯裕,從而支持更大的 Redis 規(guī)模诡右。
Redis 有什么缺點(diǎn)
- 1、由于 Redis 是內(nèi)存數(shù)據(jù)庫轻猖,所以帆吻,單臺機(jī)器,存儲的數(shù)據(jù)量咙边,跟機(jī)器本身的內(nèi)存大小猜煮。雖然 Redis 本身有 Key 過期策略,但是還是需要提前預(yù)估和節(jié)約內(nèi)存败许。如果內(nèi)存增長過快王带,需要定期刪除數(shù)據(jù)。
- 2市殷、如果進(jìn)行完整重同步愕撰,由于需要生成 RDB 文件,并進(jìn)行傳輸醋寝,會占用主機(jī)的 CPU 搞挣,并會消耗現(xiàn)網(wǎng)的帶寬。
- 3音羞、修改配置文件囱桨,進(jìn)行重啟,將硬盤中的數(shù)據(jù)加載進(jìn)內(nèi)存嗅绰,時(shí)間比較久舍肠。在這個(gè)過程中搀继,Redis 不能提供服務(wù)。
Redis 和 Memcached 的區(qū)別有哪些翠语?
1. Redis 支持復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
- Memcached 僅提供簡單的字符串叽躯。
- Redis 提供復(fù)雜的數(shù)據(jù)結(jié)構(gòu),豐富的數(shù)據(jù)操作肌括。
2. Redis 原生支持集群模式
3. 性能對比
- Redis 只使用單核险毁,而 Memcached 可以使用多核,所以平均每一個(gè)核上 Redis在存儲小數(shù)據(jù)時(shí)比 Memcached 性能更高们童。
- 在 100k 以上的數(shù)據(jù)中畔况,Memcached 性能要高于 Redis 。雖然 Redis 最近也在存儲大數(shù)據(jù)的性能上進(jìn)行優(yōu)化慧库,但是比起 Memcached跷跪,還是稍有遜色。
4. 內(nèi)存管理機(jī)制不同
相比來說齐板,Redis 的內(nèi)存管理機(jī)制吵瞻,會更加簡單。
- Redis 采用的是包裝的 malloc/free 甘磨,使用時(shí)現(xiàn)場申請的方式橡羞。
- Memcached 采用的是 Slab Allocation 機(jī)制管理內(nèi)存,預(yù)分配的內(nèi)存池的方式济舆。
如果對比兩者的內(nèi)存使用效率:
- 簡單的 Key-Value 存儲的話卿泽,Memcached 的內(nèi)存利用率更高,可以使用類似內(nèi)存池滋觉。
- 如果 Redis 采用 hash 結(jié)構(gòu)來做 key-value 存儲签夭,由于其組合式的壓縮, 其內(nèi)存利用率會高于 Memcached 椎侠。
5. 網(wǎng)絡(luò) IO 模型
- Memcached 是多線程第租,非阻塞 IO 復(fù)用的網(wǎng)絡(luò)模型,原型上接近 Nignx 我纪。
- Redis 使用單線程的 IO 復(fù)用模型慎宾,自己封裝了一個(gè)簡單的 AeEvent 事件處理框架,主要實(shí)現(xiàn)了 epoll 浅悉, kqueue 和 select 趟据,更接近 Apache 早期的模式。
6. 持久化存儲
- Memcached 不支持持久化存儲仇冯,重啟時(shí)之宿,數(shù)據(jù)被清空族操。
- Redis 支持持久化存儲苛坚,重啟時(shí)比被,可以恢復(fù)已持久化的數(shù)據(jù)。
請說說 Redis 的線程模型泼舱?
非阻塞 IO 等缀,多路復(fù)用。
Redis 內(nèi)部使用文件事件處理器 file event handler
娇昙,這個(gè)文件事件處理器是單線程的尺迂,所以 Redis 才叫做單線程的模型。它采用 IO 多路復(fù)用機(jī)制同時(shí)監(jiān)聽多個(gè) Socket冒掌,根據(jù) Socket 上的事件來選擇對應(yīng)的事件處理器進(jìn)行處理噪裕。
文件事件處理器的結(jié)構(gòu)包含 4 個(gè)部分:
- 多個(gè) Socket 。
- IO 多路復(fù)用程序股毫。
- 文件事件分派器膳音。
- 事件處理器(連接應(yīng)答處理器、命令請求處理器铃诬、命令回復(fù)處理器)祭陷。
多個(gè) Socket 可能會并發(fā)產(chǎn)生不同的操作,每個(gè)操作對應(yīng)不同的文件事件趣席,但是 IO 多路復(fù)用程序會監(jiān)聽多個(gè) socket兵志,會將 socket 產(chǎn)生的事件放入隊(duì)列中排隊(duì),事件分派器每次從隊(duì)列中取出一個(gè)事件宣肚,把該事件交給對應(yīng)的事件處理器進(jìn)行處理想罕。
來看客戶端與 redis 的一次通信過程:
客戶端 Socket01 向 Redis 的 Server Socket 請求建立連接,此時(shí) Server Socket 會產(chǎn)生一個(gè)
AE_READABLE
事件霉涨,IO 多路復(fù)用程序監(jiān)聽到 server socket 產(chǎn)生的事件后弧呐,將該事件壓入隊(duì)列中。文件事件分派器從隊(duì)列中獲取該事件嵌纲,交給連接應(yīng)答處理器
俘枫。連接應(yīng)答處理器會創(chuàng)建一個(gè)能與客戶端通信的 Socket01,并將該 Socket01 的AE_READABLE
事件與命令請求處理器關(guān)聯(lián)逮走。假設(shè)此時(shí)客戶端發(fā)送了一個(gè)
set key value
請求鸠蚪,此時(shí) Redis 中的 Socket01 會產(chǎn)生AE_READABLE
事件,IO 多路復(fù)用程序?qū)⑹录喝腙?duì)列师溅,此時(shí)事件分派器從隊(duì)列中獲取到該事件茅信,由于前面 Socket01 的AE_READABLE
事件已經(jīng)與命令請求處理器關(guān)聯(lián),因此事件分派器將事件交給命令請求處理器來處理墓臭。命令請求處理器讀取 Scket01 的set key value
并在自己內(nèi)存中完成set key value
的設(shè)置蘸鲸。操作完成后,它會將 Scket01 的AE_WRITABLE
事件與令回復(fù)處理器關(guān)聯(lián)窿锉。如果此時(shí)客戶端準(zhǔn)備好接收返回結(jié)果了酌摇,那么 Redis 中的 Socket01 會產(chǎn)生一個(gè)
AE_WRITABLE
事件膝舅,同樣壓入隊(duì)列中,事件分派器找到相關(guān)聯(lián)的命令回復(fù)處理器窑多,由命令回復(fù)處理器對 socket01 輸入本次操作的一個(gè)結(jié)果仍稀,比如ok
,之后解除 Socket01 的AE_WRITABLE
事件與命令回復(fù)處理器的關(guān)聯(lián)埂息。
為什么 Redis 單線程模型也能效率這么高技潘?
1、C 語言實(shí)現(xiàn)千康。
2享幽、純內(nèi)存操作。
3拾弃、基于非阻塞的 IO 多路復(fù)用機(jī)制琉闪。
4、單線程砸彬,避免了多線程的頻繁上下文切換問題颠毙。
-
5、豐富的數(shù)據(jù)結(jié)構(gòu)砂碉。
Redis 全程使用 hash 結(jié)構(gòu)蛀蜜,讀取速度快,還有一些特殊的數(shù)據(jù)結(jié)構(gòu)增蹭,對數(shù)據(jù)存儲進(jìn)行了優(yōu)化滴某。例如,壓縮表滋迈,對短數(shù)據(jù)進(jìn)行壓縮存儲霎奢;再再如,跳表饼灿,使用有序的數(shù)據(jù)結(jié)構(gòu)加快讀取的速度幕侠。
也因?yàn)?Redis 是單線程的,所以可以實(shí)現(xiàn)豐富的數(shù)據(jù)結(jié)構(gòu)碍彭,無需考慮并發(fā)的問題晤硕。
Redis 是單線程的,如何提高多核 CPU 的利用率庇忌?
可以在同一個(gè)服務(wù)器部署多個(gè) Redis 的實(shí)例舞箍,并把他們當(dāng)作不同的服務(wù)器來使用,在某些時(shí)候皆疹,無論如何一個(gè)服務(wù)器是不夠的疏橄, 所以,如果你想使用多個(gè) CPU 略就,你可以考慮一下分區(qū)捎迫。
Redis 有幾種持久化方式晃酒?
Redis 提供了兩種方式,實(shí)現(xiàn)數(shù)據(jù)的持久化到硬盤立砸。
1掖疮、【全量】RDB 持久化初茶,在指定的時(shí)間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤颗祝。實(shí)際操作過程是,fork 一個(gè)子進(jìn)程恼布,先將數(shù)據(jù)集寫入臨時(shí)文件螺戳,寫入成功后,再替換之前的文件折汞,用二進(jìn)制壓縮存儲倔幼。
2、【增量】AOF持久化爽待,以日志的形式記錄服務(wù)器所處理的每一個(gè)寫损同、刪除操作,查詢操作不會記錄鸟款,以文本的方式記錄膏燃,可以打開文件看到詳細(xì)的操作記錄。
RDB持久化優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 靈活設(shè)置備份頻率和周期何什。
- 非常適合冷備份组哩,對于災(zāi)難恢復(fù)而言,RDB 是非常不錯(cuò)的選擇处渣。因?yàn)槲覀兛梢苑浅]p松的將一個(gè)單獨(dú)的文件壓縮后再轉(zhuǎn)移到其它存儲介質(zhì)上伶贰。對于 Redis 的服務(wù)進(jìn)程而言,在開始持久化時(shí)罐栈,它唯一需要做的只是 fork 出子進(jìn)程黍衙,之后再由子進(jìn)程完成這些持久化的工作,這樣就可以極大的避免服務(wù)進(jìn)程執(zhí)行 IO 操作了荠诬。也就是說们豌,RDB 對 Redis 對外提供的讀寫服務(wù),影響非常小浅妆,可以讓 Redis 保持高性能望迎。
- 恢復(fù)更快。相比于 AOF 機(jī)制凌外,RDB 的恢復(fù)速度更更快辩尊,更適合恢復(fù)數(shù)據(jù),特別是在數(shù)據(jù)集非常大的情況康辑。
缺點(diǎn)
如果想保證數(shù)據(jù)的高可用性摄欲,即最大限度的避免數(shù)據(jù)丟失轿亮,那么 RDB 將不是一個(gè)很好的選擇。因?yàn)橄到y(tǒng)一旦在定時(shí)持久化之前出現(xiàn)宕機(jī)現(xiàn)象胸墙,此前沒有來得及寫入磁盤的數(shù)據(jù)都將丟失我注。所以,RDB 實(shí)際場景下迟隅,需要和 AOF 一起使用但骨。
由于 RDB 是通過 fork 子進(jìn)程來協(xié)助完成數(shù)據(jù)持久化工作的,因此智袭,如果當(dāng)數(shù)據(jù)集較大時(shí)奔缠,可能會導(dǎo)致整個(gè)服務(wù)器停止服務(wù)幾百毫秒,甚至是 1 秒鐘吼野。所以校哎,RDB 建議在業(yè)務(wù)低估,例如在半夜執(zhí)行瞳步。
AOF持久化優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
該機(jī)制可以帶來更高的數(shù)據(jù)安全性闷哆,即數(shù)據(jù)持久性。Redis 中提供了 3 種同步策略:即每秒同步单起、每修改(執(zhí)行一個(gè)命令)同步和不同步抱怔。
- 1.每秒同步:異步完成的,其效率也是非常高的馏臭,所差的是一旦系統(tǒng)出現(xiàn)宕機(jī)現(xiàn)象野蝇,那么這一秒鐘之內(nèi)修改的數(shù)據(jù)將會丟失。
- 2.每修改同步括儒,我們可以將其視為同步持久化绕沈,即每次發(fā)生的數(shù)據(jù)變化都會被立即記錄到磁盤中“镅埃可以預(yù)見乍狐,這種方式在效率上是最低的。
- 3.不同步固逗,無需多言浅蚪。
由于該機(jī)制對日志文件的寫入操作采用的是 append 模式,因此在寫入過程中即使出現(xiàn)宕機(jī)現(xiàn)象烫罩,也不會破壞日志文件中已經(jīng)存在的內(nèi)容惜傲。因?yàn)橐?append-only 模式寫入,所以沒有任何磁盤尋址的開銷贝攒,寫入性能非常高盗誊。
另外,如果我們本次操作只是寫入了一半數(shù)據(jù)就出現(xiàn)了系統(tǒng)崩潰問題,不用擔(dān)心哈踱,在 Redis 下一次啟動(dòng)之前荒适,我們可以通過 redis-check-aof 工具來幫助我們解決數(shù)據(jù)一致性的問題。
如果 AOF 日志過大开镣,Redis 可以自動(dòng)啟用 rewrite 機(jī)制刀诬。即使出現(xiàn)后臺重寫操作,也不會影響客戶端的讀寫邪财。因?yàn)樵?rewrite log 的時(shí)候陕壹,會對其中的指令進(jìn)行壓縮,創(chuàng)建出一份需要恢復(fù)數(shù)據(jù)的最小日志出來卧蜓。再創(chuàng)建新日志文件的時(shí)候帐要,老的日志文件還是照常寫入把敞。當(dāng)新的 merge 后的日志文件 ready 的時(shí)候弥奸,再交換新老日志文件即可。
注意奋早,AOF rewrite 機(jī)制盛霎,和 RDB 一樣,也需要 fork 出一次子進(jìn)程耽装,如果 Redis 內(nèi)存比較大愤炸,可能會因?yàn)?fork 阻塞下主進(jìn)程。AOF 包含一個(gè)格式清晰掉奄、易于理解的日志文件用于記錄所有的修改操作规个。事實(shí)上,我們也可以通過該文件完成數(shù)據(jù)的重建姓建。
缺點(diǎn)
對于相同數(shù)量的數(shù)據(jù)集而言诞仓,AOF 文件通常要大于 RDB 文件。RDB 在恢復(fù)大數(shù)據(jù)集時(shí)的速度比 AOF 的恢復(fù)速度要快速兔。
根據(jù)同步策略的不同墅拭,AOF 在運(yùn)行效率上往往會慢于 RDB 』凉罚總之谍婉,每秒同步策略的效率是比較高的,同步禁用策略的效率和 RDB 一樣高效镀钓。
以前 AOF 發(fā)生過 bug 穗熬,就是通過 AOF 記錄的日志,進(jìn)行數(shù)據(jù)恢復(fù)的時(shí)候丁溅,沒有恢復(fù)一模一樣的數(shù)據(jù)出來唤蔗。所以說,類似 AOF 這種較為復(fù)雜的基于命令日志/merge/回放的方式,比基于 RDB 每次持久化一份完整的數(shù)據(jù)快照文件的方式措译,更加脆弱一些别凤,容易有 bug 。不過 AOF 就是為了避免 rewrite 過程導(dǎo)致的 bug 领虹,因此每次 rewrite 并不是基于舊的指令日志進(jìn)行 merge 的规哪,而是基于當(dāng)時(shí)內(nèi)存中的數(shù)據(jù)進(jìn)行指令的重新構(gòu)建,這樣健壯性會好很多塌衰。
如何選擇持久化
不要僅僅使用 RDB诉稍,因?yàn)槟菢訒?dǎo)致你丟失很多數(shù)據(jù)。也不要僅僅使用 AOF最疆,因?yàn)槟菢佑袃蓚€(gè)問題杯巨,第一,你通過 AOF 做冷備努酸,沒有 RDB 做冷備服爷,來的恢復(fù)速度更快; 第二,RDB 每次簡單粗暴生成數(shù)據(jù)快照获诈,更加健壯仍源,可以避免 AOF 這種復(fù)雜的備份和恢復(fù)機(jī)制的 bug
Redis 支持同時(shí)開啟開啟兩種持久化方式,我們可以綜合使用 AOF 和 RDB 兩種持久化機(jī)制舔涎,用 AOF 來保證數(shù)據(jù)不丟失笼踩,作為數(shù)據(jù)恢復(fù)的第一選擇; 用 RDB 來做不同程度的冷備,在 AOF 文件都丟失或損壞不可用的時(shí)候亡嫌,還可以使用 RDB 來進(jìn)行快速的數(shù)據(jù)恢復(fù)嚎于。
如果同時(shí)使用 RDB 和 AOF 兩種持久化機(jī)制,那么在 Redis 重啟的時(shí)候挟冠,會使用 AOF 來重新構(gòu)建數(shù)據(jù)于购,因?yàn)?AOF 中的數(shù)據(jù)更加完整。
Redis 有幾種數(shù)據(jù)“過期”策略圃郊?
Redis 的過期策略:當(dāng) Redis 中緩存的 key 過期了价涝,Redis 如何處理。Redis 提供了 3 種數(shù)據(jù)過期策略:
- 被動(dòng)刪除:當(dāng)讀/寫一個(gè)已經(jīng)過期的 key 時(shí)持舆,會觸發(fā)惰性刪除策略色瘩,直接刪除掉這個(gè)過期 key 。
- 主動(dòng)刪除:由于惰性刪除策略無法保證冷數(shù)據(jù)被及時(shí)刪掉逸寓,所以 Redis 會定期主動(dòng)淘汰一批已過期的 key 居兆。
- 主動(dòng)刪除:當(dāng)前已用內(nèi)存超過 maxmemory 限定時(shí),觸發(fā)主動(dòng)清理策略竹伸,
在 Redis 中泥栖,同時(shí)使用了上述 3 種策略簇宽,即它們非互斥的。想要進(jìn)一步了解吧享,可以看看 《關(guān)于 Redis 數(shù)據(jù)過期策略》 文章禾酱。
Redis 有哪幾種數(shù)據(jù)“淘汰”策略呻袭?
Redis 內(nèi)存數(shù)據(jù)集大小上升到一定大小的時(shí)候搬男,就會進(jìn)行數(shù)據(jù)淘汰策略募谎。Redis 提供了 6 種數(shù)據(jù)淘汰策略:
- 1.volatile-lru:從已設(shè)置過期時(shí)間的數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰。redis并不是保證取得所有數(shù)據(jù)集中最近最少使用的鍵值對殊鞭,而只是隨機(jī)挑選的幾個(gè)鍵值對中的遭垛, 當(dāng)內(nèi)存達(dá)到限制的時(shí)候無法寫入非過期時(shí)間的數(shù)據(jù)集。
- 2.volatile-ttl:從已設(shè)置過期時(shí)間的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰操灿。redis 并不是保證取得所有數(shù)據(jù)集中最近將要過期的鍵值對锯仪,而只是隨機(jī)挑選的幾個(gè)鍵值對中的, 當(dāng)內(nèi)存達(dá)到限制的時(shí)候無法寫入非過期時(shí)間的數(shù)據(jù)集趾盐。
- 3.volatile-random:從已設(shè)置過期時(shí)間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰庶喜。當(dāng)內(nèi)存達(dá)到限制的時(shí)候無法寫入非過期時(shí)間的數(shù)據(jù)集。
- 4.allkeys-lru:從數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰谤碳。當(dāng)內(nèi)存達(dá)到限制的時(shí)候溃卡,對所有數(shù)據(jù)集挑選最近最少使用的數(shù)據(jù)淘汰溢豆,可寫入新的數(shù)據(jù)集蜒简。
- 5.allkeys-random:從數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰,當(dāng)內(nèi)存達(dá)到限制的時(shí)候漩仙,對所有數(shù)據(jù)集挑選隨機(jī)淘汰搓茬,可寫入新的數(shù)據(jù)集。
- 6.【默認(rèn)策略】no-enviction:當(dāng)內(nèi)存達(dá)到限制的時(shí)候队他,不淘汰任何數(shù)據(jù)卷仑,不可寫入任何數(shù)據(jù)集,所有引起申請內(nèi)存的命令會報(bào)錯(cuò)麸折。
如何選擇淘汰策略
allkeys-lru:如果我們的應(yīng)用對緩存的訪問符合冪律分布锡凝,也就是存在相對熱點(diǎn)數(shù)據(jù),或者我們不太清楚我們應(yīng)用的緩存訪問分布狀況垢啼,我們可以選擇allkeys-lru策略窜锯。
allkeys-random:如果我們的應(yīng)用對于緩存key的訪問概率相等,則可以使用這個(gè)策略芭析。
volatile-ttl:這種策略使得我們可以向Redis提示哪些key更適合被收回锚扎。
另外,volatile-lru策略和volatile-random策略適合我們將一個(gè)Redis實(shí)例既應(yīng)用于緩存和又應(yīng)用于持久化存儲的時(shí)候馁启,然而我們也可以通過使用兩個(gè)Redis實(shí)例來達(dá)到相同的效果驾孔,值得一提的是將key設(shè)置過期時(shí)間實(shí)際上會消耗更多的內(nèi)存,因此我們建議使用allkeys-lru策略從而更有效率的使用內(nèi)存。
Redis 回收進(jìn)程如何工作的翠勉?
一個(gè)客戶端運(yùn)行了新的寫命令妖啥,添加了新的數(shù)據(jù)。Redis 檢查內(nèi)存Redis 執(zhí)行新命令对碌。
如果有大量的 key 需要設(shè)置同一時(shí)間過期迹栓,一般需要注意什么?
如果大量的 key 過期時(shí)間設(shè)置的過于集中俭缓,到過期的那個(gè)時(shí)間點(diǎn)克伊,Redis可能會出現(xiàn)短暫的卡頓現(xiàn)象。一般需要在時(shí)間上加一個(gè)隨機(jī)值华坦,使得過期時(shí)間分散一些愿吹。
Redis 有哪些數(shù)據(jù)結(jié)構(gòu)?
如果你是 Redis 普通玩家惜姐,可能你的回答是如下五種數(shù)據(jù)結(jié)構(gòu):
- 字符串 String
- 字典Hash
- 列表List
- 集合Set
- 有序集合 SortedSet
如果你是 Redis 中級玩家犁跪,還需要加上下面幾種數(shù)據(jù)結(jié)構(gòu):
- HyperLogLog
- Geo
- Bitmap
如果你是 Redis 高端玩家,你可能玩過 Redis Module 歹袁,可以再加上下面幾種數(shù)據(jù)結(jié)構(gòu):
- BloomFilter
- RedisSearch
- Redis-ML
- JSON
聊聊 Redis 使用場景
Redis 可用的場景非常之多:
- 數(shù)據(jù)緩存
- 分布式鎖
- 會話緩存:如將 web session 存放在 Redis 中坷衍。
- 時(shí)效性數(shù)據(jù):如驗(yàn)證碼只有60秒有效期,超過時(shí)間無法使用
- 訪問頻率:出于減輕服務(wù)器的壓力控制訪問頻率条舔,如限制 IP 在一段時(shí)間的訪問量
- 計(jì)數(shù)器:如點(diǎn)贊數(shù)枫耳、收藏?cái)?shù)、分享數(shù)等
- 社交列表:社交屬性相關(guān)的列表信息孟抗,如用戶點(diǎn)贊列表迁杨、用戶分享列表
- 記錄用戶判定信息:如用戶是否點(diǎn)贊、用戶是否收藏凄硼、用戶是否分享
- 交集铅协、并集和差集:如實(shí)現(xiàn)共同好友,共同關(guān)注摊沉,共同偏好等社交關(guān)系
- 熱門列表與排行榜:按照得分進(jìn)行排序狐史,如展示最熱、點(diǎn)擊率最高说墨、活躍度最高
- 最新動(dòng)態(tài):按照時(shí)間順序排列的最新動(dòng)態(tài)骏全,使用 Sorted Set 類型的分?jǐn)?shù)權(quán)重存儲 Unix 時(shí)間戳進(jìn)行排序
- 消息隊(duì)列:Redis 能作為一個(gè)很好的消息隊(duì)列來使用,依賴 List 類型利用 LPUSH 命令將數(shù)據(jù)添加到鏈表頭部婉刀,通過 BRPOP 命令將元素從鏈表尾部取出吟温。同時(shí),市面上成熟的消息隊(duì)列產(chǎn)品有很多突颊,例如 RabbitMQ鲁豪。因此潘悼,更加建議使用 RabbitMQ 作為消息中間件。
Redis 支持的 Java 客戶端都有哪些爬橡?
使用比較廣泛的有三個(gè) Java 客戶端:
- Redisson:是一個(gè)高級的分布式協(xié)調(diào) Redis 客服端治唤,能幫助用戶在分布式環(huán)境中輕松實(shí)現(xiàn)一些 Java 的對象。
- Jedis: Redis 的 Java 實(shí)現(xiàn)的客戶端糙申,其 API 提供了比較全面的 Redis 命令的支持宾添。
- Lettuce:一個(gè)可伸縮線程安全的 Redis 客戶端。多個(gè)線程可以共享同一個(gè) RedisConnection 柜裸。它利用優(yōu)秀 Netty NIO 框架來高效地管理多個(gè)連接缕陕。
Redis 官方推薦使用 Redisson 或 Jedis 。
如何使用 Redis 實(shí)現(xiàn)分布式鎖疙挺?
方案一:set 指令
先拿 setnx 來爭搶鎖扛邑,搶到之后,再用 expire 給鎖加一個(gè)過期時(shí)間防止鎖忘記了釋放铐然。這種方式會有問題蔬崩,如果在 setnx 之后執(zhí)行 expire 之前進(jìn)程意外 crash 或者要重啟維護(hù)了,那會怎么樣搀暑?這個(gè)鎖就永遠(yuǎn)得不到釋放了沥阳。
set 指令有非常復(fù)雜的參數(shù),可以同時(shí)把 setnx 和 expire 合成一條指令來用的自点!
public class RedisTool {
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
/**
* 嘗試獲取分布式鎖
* @param jedis Redis客戶端
* @param lockKey 鎖
* @param requestId 請求標(biāo)識
* @param expireTime 超期時(shí)間
* @return 是否獲取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
可以看到桐罕,我們加鎖就一行代碼:jedis.set(String key, String value, String nxxx, String expx, int time),這個(gè)set()方法一共有五個(gè)形參:
第一個(gè)為key樟氢,我們使用key來當(dāng)鎖冈绊,因?yàn)閗ey是唯一的。
第二個(gè)為value埠啃,我們傳的是requestId,很多童鞋可能不明白伟恶,有key作為鎖不就夠了嗎碴开,為什么還要用到value?通過給value賦值為requestId博秫,我們就知道這把鎖是哪個(gè)請求加的了潦牛,在解鎖的時(shí)候就可以有依據(jù)。requestId可以使用UUID.randomUUID().toString()方法生成挡育。
第三個(gè)為nxxx巴碗,這個(gè)參數(shù)我們填的是NX,意思是SET IF NOT EXIST即寒,即當(dāng)key不存在時(shí)橡淆,我們進(jìn)行set操作召噩;若key已經(jīng)存在,則不做任何操作逸爵;
第四個(gè)為expx具滴,這個(gè)參數(shù)我們傳的是PX,意思是我們要給這個(gè)key加一個(gè)過期的設(shè)置师倔,具體時(shí)間由第五個(gè)參數(shù)決定构韵。
第五個(gè)為time,與第四個(gè)參數(shù)相呼應(yīng)趋艘,代表key的過期時(shí)間疲恢。
具體的實(shí)現(xiàn),可以參考如下文章:* 《Redis 分布式鎖的正確實(shí)現(xiàn)方式(Java 版)》
方案二:Redlock
set 指令的方案瓷胧,適合用于在單機(jī) Redis 節(jié)點(diǎn)的場景下冈闭,在多 Redis 節(jié)點(diǎn)的場景下,會存在分布式鎖丟失的問題抖单。所以萎攒,Redis 作者 Antirez 基于分布式環(huán)境下提出了一種更高級的分布式鎖的實(shí)現(xiàn)方式:Redlock 。
具體的源碼解析矛绘,可以看看 《精盡 Redisson 源碼分析 —— 可靠分布式鎖 RedLock》 文章耍休。
具體的方案,胖友可以看看老友飛哥的兩篇博客:
最近畫了一個(gè) Redisson 實(shí)現(xiàn)分布式鎖的流程圖货矮,胖友可以點(diǎn)擊傳送門閱讀羊精。
對比 Zookeeper 分布式鎖
- 從可靠性上來說,Zookeeper 分布式鎖好于 Redis 分布式鎖囚玫。
- 從性能上來說喧锦,Redis 分布式鎖好于 Zookeeper 分布式鎖。
如何使用 Redis 實(shí)現(xiàn)消息隊(duì)列抓督?
一般使用 list 結(jié)構(gòu)作為隊(duì)列燃少,rpush 生產(chǎn)消息,lpop 消費(fèi)消息铃在。當(dāng) lpop 沒有消息的時(shí)候阵具,要適當(dāng) sleep 一會再重試。
如果對方追問可不可以不用 sleep 呢定铜?list 還有個(gè)指令叫 blpop 阳液,在沒有消息的時(shí)候,它會阻塞住直到消息到來揣炕。
如果對方追問能不能生產(chǎn)一次消費(fèi)多次呢帘皿?使用 pub / sub 主題訂閱者模式,可以實(shí)現(xiàn) 1:N 的消息隊(duì)列畸陡。
如果對方追問 pub / sub 有什么缺點(diǎn)鹰溜?在消費(fèi)者下線的情況下虽填,生產(chǎn)的消息會丟失,得使用專業(yè)的消息隊(duì)列如 rabbitmq 等奉狈。
-
如果對方追問 redis 如何實(shí)現(xiàn)延時(shí)隊(duì)列卤唉?使用 sortedset ,拿時(shí)間戳作為 score 桑驱,消息內(nèi)容作為 key 調(diào)用 zadd 來生產(chǎn)消息跛蛋,消費(fèi)者用 zrangebyscore 指令獲取 N 秒之前的數(shù)據(jù)輪詢進(jìn)行處理。
可以看看 《Redis 學(xué)習(xí)筆記之延時(shí)隊(duì)列》 押框。面試中理逊,能回答到 Redis zset 實(shí)現(xiàn)延遲隊(duì)列,還是蠻加分的晋被。
實(shí)際上 Redis 真的真的真的不推薦作為消息隊(duì)列使用,它最多只是消息隊(duì)列的存儲層挂脑,上層的邏輯欲侮,還需要做大量的封裝和支持崭闲。
什么是 Redis Pipelining ?
一次請求/響應(yīng)服務(wù)器能實(shí)現(xiàn)處理新的請求即使舊的請求還未被響應(yīng)威蕉。這樣就可以將多個(gè)命令發(fā)送到服務(wù)器刁俭,而不用等待回復(fù),最后在一個(gè)步驟中讀取該答復(fù)忘伞。Redis Pipelining 是 Redis Client 實(shí)現(xiàn)的功能薄翅,而不是 Redis Server 提供的特性。假設(shè)我們有 3 個(gè)請求進(jìn)行下舉例子氓奈。
- 未使用 Pipeline 時(shí),那么整個(gè)執(zhí)行的順序是鼎天,req1->req2->req3 舀奶。
- 在使用 Pipeline 時(shí),那么整個(gè)執(zhí)行的順序是斋射,[req1,req2,req3] 一起發(fā)給 Redis Server 育勺,而 Redis Server 收到請求后但荤,一個(gè)一個(gè)請求進(jìn)行執(zhí)行,然后響應(yīng)涧至,不會進(jìn)行什么特殊處理腹躁。而 Client 在收到 resp1,resp2,resp3 后,進(jìn)行響應(yīng)給業(yè)務(wù)上層南蓬。
所以纺非,Pipeline 的作用,是避免每發(fā)一個(gè)請求赘方,就阻塞等待這個(gè)請求的結(jié)果烧颖。
這就是管道(pipelining),是一種幾十年來廣泛使用的技術(shù)窄陡。例如許多 POP3 協(xié)議已經(jīng)實(shí)現(xiàn)支持這個(gè)功能,大大加快了從服務(wù)器下載新郵件的過程涂圆。
Redis 很早就支持管道(pipelining)技術(shù)润歉,因此無論你運(yùn)行的是什么版本,你都可以使用管道(pipelining)操作 Redis九妈。
Redis 如何做大量數(shù)據(jù)插入萌朱?
Redis 2.6 開始晶疼,Redis-cli 支持一種新的被稱之為 pipe mode 的新模式用于執(zhí)行大量數(shù)據(jù)插入工作。
什么是 Redis 事務(wù)蠢莺?
可以一次性執(zhí)行多條命令锄弱,本質(zhì)上是一組命令的集合会宪。一個(gè)事務(wù)中的所有命令都會序列化塞帐,然后按順序地串行化執(zhí)行壁榕,而不會被插入其他命令
事務(wù)相關(guān)的命令
- 1)DISCARD:取消事務(wù)牌里,放棄執(zhí)行事務(wù)塊中的所有命令
- 2)EXEC:執(zhí)行事務(wù)塊中的命令
- 3)MULTI:標(biāo)記一個(gè)事務(wù)的開始
- 4)UNWATCH:取消WATCH命令對所有 key 的監(jiān)視
- 5)WATCH key [key...]:監(jiān)視一個(gè)(或多個(gè))key,如果在事務(wù)之前執(zhí)行這個(gè)(或者這些)key被其他命令所改動(dòng)态辛,那么事務(wù)將會被打斷奏黑。樂觀鎖
事務(wù)報(bào)錯(cuò)問題
- 1)語句錯(cuò)誤:會直接在添加隊(duì)列的時(shí)候報(bào)錯(cuò),如果出現(xiàn)這個(gè)錯(cuò)誤蹂匹,則整個(gè)事務(wù)都會回滾
- 2)邏輯錯(cuò)誤:例如給一個(gè)字符串 + 1限寞,在執(zhí)行的時(shí)候才會報(bào)錯(cuò)履植。這種錯(cuò)誤則不會影響事務(wù)中的其他操作,只有本條會報(bào)錯(cuò)
事務(wù)特性
1鼠渺、單獨(dú)的隔離操作:事務(wù)中的所有命令都會序列化拦盹、按順序執(zhí)行普舆。事務(wù)執(zhí)行過程中沼侣,不會被其他客戶端發(fā)送來的命令請求打斷蛾洛。
2轧膘、沒有隔離級別的概念:隊(duì)列中的命令沒有提交之前不會實(shí)際的被執(zhí)行谎碍,因?yàn)槭聞?wù)提交前任何指令都不會被實(shí)際執(zhí)行,也就不存在“事務(wù)內(nèi)的查詢要看到是物理的更新熔任,在事務(wù)外查詢不能看到這個(gè)問題了”
3笋敞、不保證原子性:redis 同一個(gè)事務(wù)中如果有一條命令執(zhí)行失敗夯巷,其后的命令仍然會被執(zhí)行,沒有回滾篮绰。除非加入隊(duì)列的時(shí)候就出錯(cuò)臀突,即類似 java 的編譯時(shí)異常和執(zhí)行時(shí)一異常候学,編譯時(shí)會導(dǎo)致回滾,執(zhí)行時(shí)異常不回滾)
Redis哨兵(Sentinel)模式
哨兵模式是一種特殊的模式隐圾,首先Redis提供了哨兵的命令,哨兵是一個(gè)獨(dú)立的進(jìn)程濒蒋,作為進(jìn)程甸各,它會獨(dú)立運(yùn)行趣倾。其原理是哨兵通過發(fā)送命令儒恋,等待Redis服務(wù)器響應(yīng),從而監(jiān)控運(yùn)行的多個(gè)Redis實(shí)例牧嫉。
這里的哨兵有兩個(gè)作用
通過發(fā)送命令酣藻,讓Redis服務(wù)器返回監(jiān)控其運(yùn)行狀態(tài)辽剧,包括主服務(wù)器和從服務(wù)器怕轿。
當(dāng)哨兵監(jiān)測到master宕機(jī)撞羽,會自動(dòng)將slave切換成master智听,然后通過發(fā)布訂閱模式通知其他的從服務(wù)器,修改配置文件惕澎,讓它們切換主機(jī)唧喉。
然而一個(gè)哨兵進(jìn)程對Redis服務(wù)器進(jìn)行監(jiān)控,可能會出現(xiàn)問題干跛,為此楼入,我們可以使用多個(gè)哨兵進(jìn)行監(jiān)控。各個(gè)哨兵之間還會進(jìn)行監(jiān)控阐肤,這樣就形成了多哨兵模式。
用文字描述一下故障切換(failover)的過程诊赊。假設(shè)主服務(wù)器宕機(jī)碧磅,哨兵1先檢測到這個(gè)結(jié)果鲸郊,系統(tǒng)并不會馬上進(jìn)行failover過程四濒,僅僅是哨兵1主觀的認(rèn)為主服務(wù)器不可用盗蟆,這個(gè)現(xiàn)象成為主觀下線。當(dāng)后面的哨兵也檢測到主服務(wù)器不可用腾供,并且數(shù)量達(dá)到一定值時(shí)节值,那么哨兵之間就會進(jìn)行一次投票,投票的結(jié)果由一個(gè)哨兵發(fā)起贴汪,進(jìn)行failover操作。切換成功后阳懂,就會通過發(fā)布訂閱模式,讓各個(gè)哨兵把自己監(jiān)控的從服務(wù)器實(shí)現(xiàn)切換主機(jī)号枕,這個(gè)過程稱為客觀下線钝腺。這樣對于客戶端而言艳狐,一切都是透明的。
如果使用 Redis Cluster 實(shí)現(xiàn)高可用?
詳細(xì)粉私,可以看看如下:https://www.cnblogs.com/williamjie/p/11132211.html
說說 Redis 哈希槽的概念抄肖?
Redis Cluster 沒有使用一致性 hash 久信,而是引入了哈希槽的概念。Redis 集群有 16384 個(gè)哈希槽漓摩,每個(gè) key 通過 CRC16 校驗(yàn)后對 16384 取模來決定放置哪個(gè)槽裙士,集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分 hash 槽。
因?yàn)樽畲笫?16384 個(gè)哈希槽管毙,所以考慮 Redis 集群中的每個(gè)節(jié)點(diǎn)都能分配到一個(gè)哈希槽腿椎,所以最多支持 16384 個(gè) Redis 節(jié)點(diǎn)。
為什么是 16384 呢夭咬?主要考慮集群內(nèi)的網(wǎng)絡(luò)帶寬掏湾,而 16384 剛好是 2K 字節(jié)大小尊浪。
Redis Cluster 的主從復(fù)制模型是怎樣的?
為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無法通信的情況下集群仍然可用嘱朽,所以集群使用了主從復(fù)制模型奋刽,每個(gè)節(jié)點(diǎn)都會有 N-1 個(gè)復(fù)制節(jié)點(diǎn)狭魂。所以,Redis Cluster 可以說是 Redis Sentinel 帶分片的加強(qiáng)版沛厨。也可以說:
- Redis Sentinel 著眼于高可用电谣,在 master 宕機(jī)時(shí)會自動(dòng)將 slave 提升為 master ,繼續(xù)提供服務(wù)。
- Redis Cluster 著眼于擴(kuò)展性朵诫,在單個(gè) Redis 內(nèi)存不足時(shí),使用 Cluster 進(jìn)行分片存儲殿遂。
Redis Cluster 方案什么情況下會導(dǎo)致整個(gè)集群不可用?
有 A,B风科,C 三個(gè)節(jié)點(diǎn)的集群玖姑,在沒有復(fù)制模型的情況下,如果節(jié)點(diǎn) B 宕機(jī)了囱稽,那么整個(gè)集群就會以為缺少 5501-11000 這個(gè)范圍的槽而不可用。當(dāng)然烤黍,這種情況也可以配置 cluster-require-full-coverage=no ,整個(gè)集群無需所有槽位覆蓋关顷。
Redis Cluster 會有寫操作丟失嗎?為什么?
Redis 并不能保證數(shù)據(jù)的強(qiáng)一致性,而是【異步復(fù)制】,這意味這在實(shí)際中集群在特定的條件下可能會丟失寫操作畸冲。
注意呀枢,無論對于 Redis Sentinel 還是 Redis Cluster 方案活尊,都是通過主從復(fù)制蛹锰,所以在數(shù)據(jù)的復(fù)制方面夸盟,都存在相同的情況拓春。
Redis 集群如何選擇數(shù)據(jù)庫?
Redis 集群目前無法做數(shù)據(jù)庫選擇,默認(rèn)在 0 數(shù)據(jù)庫江咳。
請說說生產(chǎn)環(huán)境中的 Redis 是怎么部署的?
Redis Cluster 甥雕,10 臺機(jī)器踩身,5 臺機(jī)器部署了 Redis 主實(shí)例,另外 5 臺機(jī)器部署了 Redis 的從實(shí)例社露,每個(gè)主實(shí)例掛了一個(gè)從實(shí)例挟阻,5 個(gè)節(jié)點(diǎn)對外提供讀寫服務(wù),每個(gè)節(jié)點(diǎn)的讀寫高峰 qps 可能可以達(dá)到每秒 5 萬峭弟,5 臺機(jī)器最多是 25 萬讀寫請求每秒赁濒。
機(jī)器是什么配置?32G 內(nèi)存 + 8 核 CPU + 1T 磁盤孟害,但是分配給 Redis 進(jìn)程的是 10G 內(nèi)存,一般線上生產(chǎn)環(huán)境挪拟,Redis 的內(nèi)存盡量不要超過 10G挨务,超過 10G 可能會有問題。那么,5 臺機(jī)器對外提供讀寫谎柄,一共有 50G 內(nèi)存丁侄。
因?yàn)槊總€(gè)主實(shí)例都掛了一個(gè)從實(shí)例,所以是高可用的朝巫,任何一個(gè)主實(shí)例宕機(jī)鸿摇,都會自動(dòng)故障遷移,Redis 從實(shí)例會自動(dòng)變成主實(shí)例繼續(xù)提供讀寫服務(wù)劈猿。
你往內(nèi)存里寫的是什么數(shù)據(jù)拙吉?每條數(shù)據(jù)的大小是多少?商品數(shù)據(jù)揪荣,每條數(shù)據(jù)是 10kb 筷黔。100 條數(shù)據(jù)是 1mb ,10 萬條數(shù)據(jù)是 1G 仗颈。常駐內(nèi)存的是 200 萬條商品數(shù)據(jù)佛舱,占用內(nèi)存是 20G ,僅僅不到總內(nèi)存的 50% 挨决。目前高峰期每秒就是 3500 左右的請求量请祖。
一般來說,當(dāng)公司體量大了之后脖祈,建議是一個(gè)業(yè)務(wù)線獨(dú)占一個(gè)或多個(gè) Redis Cluster 集群肆捕,實(shí)現(xiàn)好業(yè)務(wù)線與業(yè)務(wù)線之間的隔離。
什么是 Redis 分區(qū)撒犀?
Redis 分區(qū)是一種模式福压,將數(shù)據(jù)分區(qū)到不同的 Redis 節(jié)點(diǎn)上,而 Redis 集群的 Redis Cluster或舞、Twemproxy荆姆、Codis、客戶端分片( 不包括 Redis Sentinel ) 這四種方案映凳,是 Redis 分區(qū)的具體實(shí)現(xiàn)胆筒。
注意,Redis Sentinel 實(shí)現(xiàn)的是 Redis 的高可用
- Redis 每個(gè)分區(qū)诈豌,如果想要實(shí)現(xiàn)高可用仆救,需要使用到 Redis 主從復(fù)制。
你知道有哪些 Redis 分區(qū)實(shí)現(xiàn)方案矫渔?
Redis 分區(qū)方案镊辕,主要分成兩種類型:
- 客戶端分區(qū)揩悄,就是在客戶端就已經(jīng)決定數(shù)據(jù)會被存儲到哪個(gè) Redis 節(jié)點(diǎn)或者從哪個(gè) Redis 節(jié)點(diǎn)讀取。大多數(shù)客戶端已經(jīng)實(shí)現(xiàn)了客戶端分區(qū)。案例:Redis Cluster 和客戶端分區(qū)晰韵。
- 代理分區(qū),意味著客戶端將請求發(fā)送給代理,然后代理決定去哪個(gè)節(jié)點(diǎn)寫數(shù)據(jù)或者讀數(shù)據(jù)。代理根據(jù)分區(qū)規(guī)則決定請求哪些 Redis 實(shí)例,然后根據(jù) Redis 的響應(yīng)結(jié)果返回給客戶端捷凄。案例:Twemproxy 和 Codis 。
Redis Cluster 實(shí)現(xiàn)了一種混合形式的查詢路由佛点,但并不是直接將請求從一個(gè)Redis 節(jié)點(diǎn)轉(zhuǎn)發(fā)到另一個(gè) Redis 節(jié)點(diǎn),而是在客戶端的幫助下直接 Redirect 到正確的 Redis 節(jié)點(diǎn)购城。
Redis 有哪些重要的健康指標(biāo)侮攀?
推薦閱讀 《Redis 幾個(gè)重要的健康指標(biāo)》
- 存活情況
- 連接數(shù)
- 阻塞客戶端數(shù)量
- 使用內(nèi)存峰值
- 內(nèi)存碎片率
- 緩存命中率
- OPS
- 持久化
- 失效KEY
- 慢日志
如何提高 Redis 命中率?
聚焦在高頻訪問且時(shí)效性要求不高的熱點(diǎn)業(yè)務(wù)上(如字典數(shù)據(jù)觅廓、session瞳脓、token)写妥,通過緩存預(yù)加載(預(yù)熱)、增加存儲容量画畅、調(diào)整緩存粒度淫僻、更新緩存等手段來提高命中率。
推薦閱讀 《如何提高緩存命中率(Redis)》 雳灵。
怎么優(yōu)化 Redis 的內(nèi)存占用棕所?
- redisObject 對象
- 縮減鍵值對象
- 共享對象池
- 字符串優(yōu)化
- 編碼優(yōu)化
- 控制 key 的數(shù)量
一個(gè) Redis 實(shí)例最多能存放多少的 keys?List悯辙、Set琳省、Sorted Set 他們最多能存放多少元素?
理論上躲撰,Redis 可以處理多達(dá) 2^32 的 keys 针贬,并且在實(shí)際中進(jìn)行了測試,每個(gè)實(shí)例至少存放了 2 億 5 千萬的 keys拢蛋。
任何 list桦他、set、和 sorted set 都可以放 2^32 個(gè)元素谆棱。
假如 Redis 里面有 1 億個(gè) key快压,其中有 10w 個(gè) key 是以某個(gè)固定的已知的前綴開頭的圆仔,如果將它們?nèi)空页鰜恚?/strong>
使用 keys
指令可以掃出指定模式的 key 列表。
- 對方接著追問:如果這個(gè) Redis 正在給線上的業(yè)務(wù)提供服務(wù)蔫劣,那使用
keys
指令會有什么問題坪郭? - 這個(gè)時(shí)候你要回答 Redis 關(guān)鍵的一個(gè)特性:Redis 的單線程的。
keys
指令會導(dǎo)致線程阻塞一段時(shí)間脉幢,線上服務(wù)會停頓截粗,直到指令執(zhí)行完畢,服務(wù)才能恢復(fù)鸵隧。這個(gè)時(shí)候可以使用scan
指令,scan
指令可以無阻塞的提取出指定模式的 key 列表意推,但是會有一定的重復(fù)概率豆瘫,在客戶端做一次去重就可以了,但是整體所花費(fèi)的時(shí)間會比直接用keys
指令長菊值。
Redis 常見的性能問題都有哪些外驱?如何解決?
1腻窒、Master 最好不要做任何持久化工作昵宇,如 RDB 內(nèi)存快照和 AOF 日志文件。
一般是主節(jié)點(diǎn)開啟 AOF 儿子,從節(jié)點(diǎn)開啟 AOF + RDB 瓦哎。
- Master 寫內(nèi)存快照,save 命令調(diào)度 rdbSave 函數(shù)柔逼,會阻塞主線程的工作蒋譬,當(dāng)快照比較大時(shí)對性能影響是非常大的,會間斷性暫停服務(wù)愉适,所以 Master 最好不要寫內(nèi)存快照犯助。
- Master AOF 持久化,如果不重寫 AOF 文件维咸,這個(gè)持久化方式對性能的影響是最小的剂买,但是 AOF 文件會不斷增大,AOF 文件過大會影響 Master 重啟的恢復(fù)速度癌蓖。
- 所以瞬哼,Master 最好不要做任何持久化工作,包括內(nèi)存快照和 AOF 日志文件费坊,特別是不要啟用內(nèi)存快照做持久化倒槐。如果數(shù)據(jù)比較關(guān)鍵,某個(gè) Slave 開啟AOF備份數(shù)據(jù)附井,策略為每秒同步一次讨越。
2两残、Master 調(diào)用 BGREWRITEAOF 重寫 AOF 文件,AOF 在重寫的時(shí)候會占大量的 CPU 和內(nèi)存資源把跨,導(dǎo)致服務(wù) load 過高人弓,出現(xiàn)短暫服務(wù)暫停現(xiàn)象着逐。
- 一般來說崔赌,出現(xiàn)這個(gè)問題,很多時(shí)候是因?yàn)?Master 的內(nèi)存過大耸别,一次 AOF 重寫需要占用的 CPU 和內(nèi)存的資源較多健芭,此時(shí)可以考慮 Redis Cluster 方案。
3秀姐、盡量避免在壓力很大的主庫上增加過多的從庫慈迈。
- 可以考慮在從上掛載其它的從。
4省有、主從復(fù)制不要用圖狀結(jié)構(gòu)痒留,用單向鏈表結(jié)構(gòu)更為穩(wěn)定,即:Master <- Slave1 <- Slave2 <- Slave3... 蠢沿。
這樣的結(jié)構(gòu)伸头,也方便解決單點(diǎn)故障問題,實(shí)現(xiàn) Slave 對 Master 的替換舷蟀。如果 Master掛了恤磷,可以立刻啟用 Slave1 做 Master ,其他不變野宜。
從節(jié)點(diǎn)在切換主節(jié)點(diǎn)作為復(fù)制源的時(shí)候碗殷,會重新發(fā)起全量復(fù)制。所以此處通過 Slave1 掛在 Slave 下速缨,可以規(guī)避這個(gè)問題锌妻。同時(shí),也減少了 Master 的復(fù)制壓力旬牲。當(dāng)然仿粹,壞處就是 Slave1 的延遲可能會高一些些,所以還是需要取舍原茅。
5吭历、Redis 主從復(fù)制的性能問題,為了主從復(fù)制的速度和連接的穩(wěn)定性擂橘,Slave 和 Master 最好在同一個(gè)局域網(wǎng)內(nèi)晌区。
修改配置不重啟 Redis 會實(shí)時(shí)生效嗎?
針對運(yùn)行實(shí)例,有許多配置選項(xiàng)可以通過 CONFIG SET 命令進(jìn)行修改朗若,而無需執(zhí)行任何形式的重啟恼五。
從 Redis 2.2 開始,可以從 AOF 切換到 RDB 的快照持久性或其他方式而不需要重啟 Redis哭懈。檢索 CONFIG GET * 命令獲取更多信息灾馒。
但偶爾重新啟動(dòng)是必須的,如為升級 Redis 程序到新的版本遣总,或者當(dāng)你需要修改某些目前 CONFIG 命令還不支持的配置參數(shù)的時(shí)候睬罗。