概述
什么是Redis
Redis(Remote Dictionary Server) 是一個(gè)使用 C 語言編寫的拦盹,開源的(BSD許可)高性能非關(guān)系型(NoSQL)的鍵值對數(shù)據(jù)庫锚烦。
Redis 可以存儲鍵和五種不同類型的值之間的映射然爆。鍵的類型只能為字符串嘹锁,值支持五種數(shù)據(jù)類型:字符串、列表、集合妙真、散列表、有序集合荚守。
與傳統(tǒng)數(shù)據(jù)庫不同的是 Redis 的數(shù)據(jù)是存在內(nèi)存中的珍德,所以讀寫速度非常快矗漾,因此 redis 被廣泛應(yīng)用于緩存方向锈候,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB敞贡。另外泵琳,Redis 也經(jīng)常用來做分布式鎖。除此之外嫡锌,Redis 支持事務(wù) 虑稼、持久化、LUA腳本势木、LRU驅(qū)動事件蛛倦、多種集群方案。
Redis有哪些優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
讀寫性能優(yōu)異啦桌, Redis能讀的速度是110000次/s溯壶,寫的速度是81000次/s甫男。
支持?jǐn)?shù)據(jù)持久化板驳,支持AOF和RDB兩種持久化方式。
支持事務(wù)慨蓝,Redis的所有操作都是原子性的,同時(shí)Redis還支持對幾個(gè)操作合并后的原子性執(zhí)行弧满。
數(shù)據(jù)結(jié)構(gòu)豐富,除了支持string類型的value外還支持hash此熬、set庭呜、zset、list等數(shù)據(jù)結(jié)構(gòu)犀忱。
支持主從復(fù)制募谎,主機(jī)會自動將數(shù)據(jù)同步到從機(jī),可以進(jìn)行讀寫分離峡碉。
缺點(diǎn)
數(shù)據(jù)庫容量受到物理內(nèi)存的限制近哟,不能用作海量數(shù)據(jù)的高性能讀寫驮审,因此Redis適合的場景主要局限在較小數(shù)據(jù)量的高性能操作和運(yùn)算上鲫寄。
Redis 不具備自動容錯(cuò)和恢復(fù)功能,主機(jī)從機(jī)的宕機(jī)都會導(dǎo)致前端部分讀寫請求失敗疯淫,需要等待機(jī)器重啟或者手動切換前端的IP才能恢復(fù)地来。
主機(jī)宕機(jī),宕機(jī)前有部分?jǐn)?shù)據(jù)未能及時(shí)同步到從機(jī)熙掺,切換IP后還會引入數(shù)據(jù)不一致的問題未斑,降低了系統(tǒng)的可用性。
Redis 較難支持在線擴(kuò)容币绩,在集群容量達(dá)到上限時(shí)在線擴(kuò)容會變得很復(fù)雜芽突。為避免這一問題,運(yùn)維人員在系統(tǒng)上線時(shí)必須確保有足夠的空間挟秤,這對資源造成了很大的浪費(fèi)。
為什么要用 Redis /為什么要用緩存
主要從“高性能”和“高并發(fā)”這兩點(diǎn)來看待這個(gè)問題啄糙。
高性能:
假如用戶第一次訪問數(shù)據(jù)庫中的某些數(shù)據(jù)。這個(gè)過程會比較慢燕雁,因?yàn)槭菑挠脖P上讀取的。將該用戶訪問的數(shù)據(jù)存在數(shù)緩存中,這樣下一次再訪問這些數(shù)據(jù)的時(shí)候就可以直接從緩存中獲取了金踪。操作緩存就是直接操作內(nèi)存,所以速度相當(dāng)快。如果數(shù)據(jù)庫中的對應(yīng)數(shù)據(jù)改變的之后怨咪,同步改變緩存中相應(yīng)的數(shù)據(jù)即可!
高并發(fā):
直接操作緩存能夠承受的請求是遠(yuǎn)遠(yuǎn)大于直接訪問數(shù)據(jù)庫的,所以我們可以考慮把數(shù)據(jù)庫中的部分?jǐn)?shù)據(jù)轉(zhuǎn)移到緩存中去油啤,這樣用戶的一部分請求會直接到緩存這里而不用經(jīng)過數(shù)據(jù)庫帜平。
為什么要用 Redis 而不用 map/guava 做緩存?
緩存分為本地緩存和分布式緩存冗锁。以 Java 為例箍邮,使用自帶的 map 或者 guava 實(shí)現(xiàn)的是本地緩存擂错,最主要的特點(diǎn)是輕量以及快速剑鞍,生命周期隨著 jvm 的銷毀而結(jié)束,并且在多實(shí)例的情況下就轧,每個(gè)實(shí)例都需要各自保存一份緩存解愤,緩存不具有一致性惋啃。
使用 redis 或 memcached 之類的稱為分布式緩存异希,在多實(shí)例的情況下扣癣,各實(shí)例共用一份緩存數(shù)據(jù),緩存具有一致性频轿。缺點(diǎn)是需要保持 redis 或 memcached服務(wù)的高可用,整個(gè)程序架構(gòu)上較為復(fù)雜膳殷。
Redis為什么這么快
1、完全基于內(nèi)存勒极,絕大部分請求是純粹的內(nèi)存操作,非常快速昨忆。數(shù)據(jù)存在內(nèi)存中,類似于 HashMap,HashMap 的優(yōu)勢就是查找和操作的時(shí)間復(fù)雜度都是O(1)独旷;
2、數(shù)據(jù)結(jié)構(gòu)簡單褐啡,對數(shù)據(jù)操作也簡單许昨,Redis 中的數(shù)據(jù)結(jié)構(gòu)是專門進(jìn)行設(shè)計(jì)的莉恼;
3、采用單線程捶惜,避免了不必要的上下文切換和競爭條件,也不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗 CPU陪捷,不用去考慮各種鎖的問題烁涌,不存在加鎖釋放鎖操作,沒有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能消耗;
4仗扬、使用多路 I/O 復(fù)用模型,非阻塞 IO;
5语盈、使用底層模型不同匀谣,它們之間底層實(shí)現(xiàn)方式以及與客戶端之間通信的應(yīng)用協(xié)議不一樣,Redis 直接自己構(gòu)建了 VM 機(jī)制 符隙,因?yàn)橐话愕南到y(tǒng)調(diào)用系統(tǒng)函數(shù)的話综芥,會浪費(fèi)一定的時(shí)間去移動和請求屠阻;
數(shù)據(jù)類型
Redis有哪些數(shù)據(jù)類型
Redis主要有5種數(shù)據(jù)類型虾啦,包括String呻率,List苞七,Set,Zset慎恒,Hash粒氧,滿足大部分的使用要求
Redis的應(yīng)用場景
總結(jié)一
計(jì)數(shù)器
可以對 String 進(jìn)行自增自減運(yùn)算,從而實(shí)現(xiàn)計(jì)數(shù)器功能节腐。Redis 這種內(nèi)存型數(shù)據(jù)庫的讀寫性能非常高外盯,很適合存儲頻繁讀寫的計(jì)數(shù)量。
緩存
將熱點(diǎn)數(shù)據(jù)放到內(nèi)存中翼雀,設(shè)置內(nèi)存的最大使用量以及淘汰策略來保證緩存的命中率饱苟。
會話緩存
可以使用 Redis 來統(tǒng)一存儲多臺應(yīng)用服務(wù)器的會話信息坦弟。當(dāng)應(yīng)用服務(wù)器不再存儲用戶的會話信息莺褒,也就不再具有狀態(tài)誊锭,一個(gè)用戶可以請求任意一個(gè)應(yīng)用服務(wù)器,從而更容易實(shí)現(xiàn)高可用性以及可伸縮性纬黎。
全頁緩存(FPC)
除基本的會話token之外,Redis還提供很簡便的FPC平臺镇眷。以Magento為例枚荣,Magento提供一個(gè)插件來使用Redis作為全頁緩存后端躺同。此外,對WordPress的用戶來說虱肄,Pantheon有一個(gè)非常好的插件 wp-redis,這個(gè)插件能幫助你以最快速度加載你曾瀏覽過的頁面呆躲。
查找表
例如 DNS 記錄就很適合使用 Redis 進(jìn)行存儲谢揪。查找表和緩存類似溅蛉,也是利用了 Redis 快速的查找特性涝桅。但是查找表的內(nèi)容不能失效峦阁,而緩存的內(nèi)容可以失效曾掂,因?yàn)榫彺娌蛔鳛榭煽康臄?shù)據(jù)來源。
消息隊(duì)列(發(fā)布/訂閱功能)
List 是一個(gè)雙向鏈表叫确,可以通過 lpush 和 rpop 寫入和讀取消息瘩将。不過最好使用 Kafka姿现、RabbitMQ 等消息中間件。
分布式鎖實(shí)現(xiàn)
在分布式場景下肖抱,無法使用單機(jī)環(huán)境下的鎖來對多個(gè)節(jié)點(diǎn)上的進(jìn)程進(jìn)行同步备典。可以使用 Redis 自帶的 SETNX 命令實(shí)現(xiàn)分布式鎖意述,除此之外提佣,還可以使用官方提供的 RedLock 分布式鎖實(shí)現(xiàn)。
其它
Set 可以實(shí)現(xiàn)交集欲险、并集等操作镐依,從而實(shí)現(xiàn)共同好友等功能。ZSet 可以實(shí)現(xiàn)有序性操作天试,從而實(shí)現(xiàn)排行榜等功能槐壳。
總結(jié)二
Redis相比其他緩存,有一個(gè)非常大的優(yōu)勢喜每,就是支持多種數(shù)據(jù)類型务唐。
數(shù)據(jù)類型說明string字符串,最簡單的k-v存儲hashhash格式带兜,value為field和value枫笛,適合ID-Detail這樣的場景。list簡單的list刚照,順序列表刑巧,支持首位或者末尾插入數(shù)據(jù)set無序list,查找速度快,適合交集啊楚、并集吠冤、差集處理sorted set有序的set
其實(shí)及刻,通過上面的數(shù)據(jù)類型的特性蛔钙,基本就能想到合適的應(yīng)用場景了。
string——適合最簡單的k-v存儲企垦,類似于memcached的存儲結(jié)構(gòu)颜价,短信驗(yàn)證碼涯保,配置信息等,就用這種類型來存儲周伦。
hash——一般key為ID或者唯一標(biāo)示夕春,value對應(yīng)的就是詳情了。如商品詳情专挪,個(gè)人信息詳情撇他,新聞詳情等。
list——因?yàn)閘ist是有序的狈蚤,比較適合存儲一些有序且數(shù)據(jù)相對固定的數(shù)據(jù)。如省市區(qū)表划纽、字典表等脆侮。因?yàn)閘ist是有序的,適合根據(jù)寫入的時(shí)間來排序勇劣,如:最新的***靖避,消息隊(duì)列等。
set——可以簡單的理解為ID-List的模式比默,如微博中一個(gè)人有哪些好友幻捏,set最牛的地方在于,可以對兩個(gè)set提供交集命咐、并集篡九、差集操作。例如:查找兩個(gè)人共同的好友等醋奠。
Sorted Set——是set的增強(qiáng)版本榛臼,增加了一個(gè)score參數(shù),自動會根據(jù)score的值進(jìn)行排序窜司。比較適合類似于top 10等不根據(jù)插入的時(shí)間來排序的數(shù)據(jù)沛善。
如上所述,雖然Redis不像關(guān)系數(shù)據(jù)庫那么復(fù)雜的數(shù)據(jù)結(jié)構(gòu)塞祈,但是金刁,也能適合很多場景,比一般的緩存數(shù)據(jù)結(jié)構(gòu)要多。了解每種數(shù)據(jù)結(jié)構(gòu)適合的業(yè)務(wù)場景尤蛮,不僅有利于提升開發(fā)效率媳友,也能有效利用Redis的性能。
持久化
什么是Redis持久化抵屿?
持久化就是把內(nèi)存的數(shù)據(jù)寫到磁盤中去庆锦,防止服務(wù)宕機(jī)了內(nèi)存數(shù)據(jù)丟失。
Redis 的持久化機(jī)制是什么轧葛?各自的優(yōu)缺點(diǎn)搂抒?
Redis 提供兩種持久化機(jī)制 RDB(默認(rèn)) 和 AOF 機(jī)制:
RDB:是Redis DataBase縮寫快照
RDB是Redis默認(rèn)的持久化方式。按照一定的時(shí)間將內(nèi)存的數(shù)據(jù)以快照的形式保存到硬盤中尿扯,對應(yīng)產(chǎn)生的數(shù)據(jù)文件為dump.rdb求晶。通過配置文件中的save參數(shù)來定義快照的周期。
優(yōu)點(diǎn):
1衷笋、只有一個(gè)文件 dump.rdb芳杏,方便持久化。
2辟宗、容災(zāi)性好爵赵,一個(gè)文件可以保存到安全的磁盤。
3泊脐、性能最大化空幻,fork 子進(jìn)程來完成寫操作,讓主進(jìn)程繼續(xù)處理命令容客,所以是 IO 最大化秕铛。使用單獨(dú)子進(jìn)程來進(jìn)行持久化,主進(jìn)程不會進(jìn)行任何 IO 操作缩挑,保證了 redis 的高性能
4.相對于數(shù)據(jù)集大時(shí)但两,比 AOF 的啟動效率更高。
缺點(diǎn):
1供置、數(shù)據(jù)安全性低谨湘。RDB 是間隔一段時(shí)間進(jìn)行持久化,如果持久化之間 redis 發(fā)生故障士袄,會發(fā)生數(shù)據(jù)丟失悲关。所以這種方式更適合數(shù)據(jù)要求不嚴(yán)謹(jǐn)?shù)臅r(shí)候)
2、AOF(Append-only file)持久化方式:是指所有的命令行記錄以 redis 命令請 求協(xié)議的格式完全持久化存儲)保存為 aof 文件娄柳。
AOF:持久化
AOF持久化(即Append Only File持久化)寓辱,則是將Redis執(zhí)行的每次寫命令記錄到單獨(dú)的日志文件中,當(dāng)重啟Redis會重新將持久化的日志中文件恢復(fù)數(shù)據(jù)赤拒。
當(dāng)兩種方式同時(shí)開啟時(shí)秫筏,數(shù)據(jù)恢復(fù)Redis會優(yōu)先選擇AOF恢復(fù)诱鞠。
優(yōu)點(diǎn):
1、數(shù)據(jù)安全这敬,aof 持久化可以配置 appendfsync 屬性航夺,有 always,每進(jìn)行一次 命令操作就記錄到 aof 文件中一次崔涂。
2阳掐、通過 append 模式寫文件,即使中途服務(wù)器宕機(jī)冷蚂,可以通過 redis-check-aof 工具解決數(shù)據(jù)一致性問題缭保。
3、AOF 機(jī)制的 rewrite 模式蝙茶。AOF 文件沒被 rewrite 之前(文件過大時(shí)會對命令 進(jìn)行合并重寫)艺骂,可以刪除其中的某些命令(比如誤操作的 flushall))
缺點(diǎn):
1、AOF 文件比 RDB 文件大隆夯,且恢復(fù)速度慢钳恕。
2、數(shù)據(jù)集大的時(shí)候蹄衷,比 rdb 啟動效率低忧额。
優(yōu)缺點(diǎn)是什么?
AOF文件比RDB更新頻率高愧口,優(yōu)先使用AOF還原數(shù)據(jù)宙址。
AOF比RDB更安全也更大
RDB性能比AOF好
如果兩個(gè)都配了優(yōu)先加載AOF
如何選擇合適的持久化方式
一般來說, 如果想達(dá)到足以媲美PostgreSQL的數(shù)據(jù)安全性调卑,你應(yīng)該同時(shí)使用兩種持久化功能。在這種情況下大咱,當(dāng) Redis 重啟的時(shí)候會優(yōu)先載入AOF文件來恢復(fù)原始的數(shù)據(jù)恬涧,因?yàn)樵谕ǔG闆r下AOF文件保存的數(shù)據(jù)集要比RDB文件保存的數(shù)據(jù)集要完整。
如果你非常關(guān)心你的數(shù)據(jù)碴巾, 但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失溯捆,那么你可以只使用RDB持久化。
有很多用戶都只使用AOF持久化厦瓢,但并不推薦這種方式提揍,因?yàn)槎〞r(shí)生成RDB快照(snapshot)非常便于進(jìn)行數(shù)據(jù)庫備份, 并且 RDB 恢復(fù)數(shù)據(jù)集的速度也要比AOF恢復(fù)的速度要快煮仇,除此之外劳跃,使用RDB還可以避免AOF程序的bug。
如果你只希望你的數(shù)據(jù)在服務(wù)器運(yùn)行的時(shí)候存在浙垫,你也可以不使用任何持久化方式刨仑。
Redis持久化數(shù)據(jù)和緩存怎么做擴(kuò)容郑诺?
如果Redis被當(dāng)做緩存使用,使用一致性哈希實(shí)現(xiàn)動態(tài)擴(kuò)容縮容杉武。
如果Redis被當(dāng)做一個(gè)持久化存儲使用辙诞,必須使用固定的keys-to-nodes映射關(guān)系,節(jié)點(diǎn)的數(shù)量一旦確定不能變化轻抱。否則的話(即Redis節(jié)點(diǎn)需要動態(tài)變化的情況)飞涂,必須使用可以在運(yùn)行時(shí)進(jìn)行數(shù)據(jù)再平衡的一套系統(tǒng),而當(dāng)前只有Redis集群可以做到這樣祈搜。
過期鍵的刪除策略
Redis的過期鍵的刪除策略
我們都知道较店,Redis是key-value數(shù)據(jù)庫,我們可以設(shè)置Redis中緩存的key的過期時(shí)間夭问。Redis的過期策略就是指當(dāng)Redis中緩存的key過期了泽西,Redis如何處理。
過期策略通常有以下三種:
定時(shí)過期:每個(gè)設(shè)置過期時(shí)間的key都需要創(chuàng)建一個(gè)定時(shí)器缰趋,到過期時(shí)間就會立即清除捧杉。該策略可以立即清除過期的數(shù)據(jù),對內(nèi)存很友好秘血;但是會占用大量的CPU資源去處理過期的數(shù)據(jù)味抖,從而影響緩存的響應(yīng)時(shí)間和吞吐量。
惰性過期:只有當(dāng)訪問一個(gè)key時(shí)灰粮,才會判斷該key是否已過期仔涩,過期則清除。該策略可以最大化地節(jié)省CPU資源粘舟,卻對內(nèi)存非常不友好熔脂。極端情況可能出現(xiàn)大量的過期key沒有再次被訪問,從而不會被清除柑肴,占用大量內(nèi)存霞揉。
定期過期:每隔一定的時(shí)間,會掃描一定數(shù)量的數(shù)據(jù)庫的expires字典中一定數(shù)量的key晰骑,并清除其中已過期的key适秩。該策略是前兩者的一個(gè)折中方案。通過調(diào)整定時(shí)掃描的時(shí)間間隔和每次掃描的限定耗時(shí)硕舆,可以在不同情況下使得CPU和內(nèi)存資源達(dá)到最優(yōu)的平衡效果秽荞。
(expires字典會保存所有設(shè)置了過期時(shí)間的key的過期時(shí)間數(shù)據(jù),其中抚官,key是指向鍵空間中的某個(gè)鍵的指針扬跋,value是該鍵的毫秒精度的UNIX時(shí)間戳表示的過期時(shí)間。鍵空間是指該Redis集群中保存的所有鍵凌节。)
Redis中同時(shí)使用了惰性過期和定期過期兩種過期策略胁住。
Redis key的過期時(shí)間和永久有效分別怎么設(shè)置趁猴?
EXPIRE和PERSIST命令。
我們知道通過expire來設(shè)置key 的過期時(shí)間彪见,那么對過期的數(shù)據(jù)怎么處理呢?
除了緩存服務(wù)器自帶的緩存失效策略之外(Redis默認(rèn)的有6中策略可供選擇)儡司,我們還可以根據(jù)具體的業(yè)務(wù)需求進(jìn)行自定義的緩存淘汰,常見的策略有兩種:
定時(shí)去清理過期的緩存余指;
當(dāng)有用戶請求過來時(shí)捕犬,再判斷這個(gè)請求所用到的緩存是否過期,過期的話就去底層系統(tǒng)得到新數(shù)據(jù)并更新緩存酵镜。
兩者各有優(yōu)劣碉碉,第一種的缺點(diǎn)是維護(hù)大量緩存的key是比較麻煩的,第二種的缺點(diǎn)就是每次用戶請求過來都要判斷緩存失效淮韭,邏輯相對比較復(fù)雜垢粮!具體用哪種方案,大家可以根據(jù)自己的應(yīng)用場景來權(quán)衡靠粪。
內(nèi)存相關(guān)
MySQL里有2000w數(shù)據(jù)蜡吧,redis中只存20w的數(shù)據(jù),如何保證redis中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)
redis內(nèi)存數(shù)據(jù)集大小上升到一定大小的時(shí)候占键,就會施行數(shù)據(jù)淘汰策略昔善。
Redis的內(nèi)存淘汰策略有哪些
Redis的內(nèi)存淘汰策略是指在Redis的用于緩存的內(nèi)存不足時(shí),怎么處理需要新寫入且需要申請額外空間的數(shù)據(jù)畔乙。
全局的鍵空間選擇性移除
noeviction:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)君仆,新寫入操作會報(bào)錯(cuò)。
allkeys-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)牲距,在鍵空間中返咱,移除最近最少使用的key。(這個(gè)是最常用的)
allkeys-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)牍鞠,在鍵空間中洛姑,隨機(jī)移除某個(gè)key。
設(shè)置過期時(shí)間的鍵空間選擇性移除
volatile-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)皮服,在設(shè)置了過期時(shí)間的鍵空間中,移除最近最少使用的key参咙。
volatile-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)龄广,在設(shè)置了過期時(shí)間的鍵空間中,隨機(jī)移除某個(gè)key蕴侧。
volatile-ttl:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)择同,在設(shè)置了過期時(shí)間的鍵空間中,有更早過期時(shí)間的key優(yōu)先移除净宵。
總結(jié)
Redis的內(nèi)存淘汰策略的選取并不會影響過期的key的處理敲才。內(nèi)存淘汰策略用于處理內(nèi)存不足時(shí)的需要申請額外空間的數(shù)據(jù)裹纳;過期策略用于處理過期的緩存數(shù)據(jù)。
Redis主要消耗什么物理資源紧武?
內(nèi)存剃氧。
Redis的內(nèi)存用完了會發(fā)生什么?
如果達(dá)到設(shè)置的上限阻星,Redis的寫命令會返回錯(cuò)誤信息(但是讀命令還可以正常返回朋鞍。)或者你可以配置內(nèi)存淘汰機(jī)制,當(dāng)Redis達(dá)到內(nèi)存上限時(shí)會沖刷掉舊的內(nèi)容妥箕。
Redis如何做內(nèi)存優(yōu)化滥酥?
可以好好利用Hash,list,sorted set,set等集合類型數(shù)據(jù),因?yàn)橥ǔG闆r下很多小的Key-Value可以用更緊湊的方式存放到一起畦幢。盡可能使用散列表(hashes)坎吻,散列表(是說散列表里面存儲的數(shù)少)使用的內(nèi)存非常小,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面宇葱。比如你的web系統(tǒng)中有一個(gè)用戶對象瘦真,不要為這個(gè)用戶的名稱,姓氏贝搁,郵箱吗氏,密碼設(shè)置單獨(dú)的key,而是應(yīng)該把這個(gè)用戶的所有信息存儲到一張散列表里面
線程模型
Redis線程模型
Redis基于Reactor模式開發(fā)了網(wǎng)絡(luò)事件處理器雷逆,這個(gè)處理器被稱為文件事件處理器(file event handler)弦讽。它的組成結(jié)構(gòu)為4部分:多個(gè)套接字、IO多路復(fù)用程序膀哲、文件事件分派器往产、事件處理器。因?yàn)槲募录峙善麝?duì)列的消費(fèi)是單線程的某宪,所以Redis才叫單線程模型仿村。
文件事件處理器使用 I/O 多路復(fù)用(multiplexing)程序來同時(shí)監(jiān)聽多個(gè)套接字, 并根據(jù)套接字目前執(zhí)行的任務(wù)來為套接字關(guān)聯(lián)不同的事件處理器兴喂。
當(dāng)被監(jiān)聽的套接字準(zhǔn)備好執(zhí)行連接應(yīng)答(accept)蔼囊、讀取(read)衣迷、寫入(write)畏鼓、關(guān)閉(close)等操作時(shí), 與操作相對應(yīng)的文件事件就會產(chǎn)生壶谒, 這時(shí)文件事件處理器就會調(diào)用套接字之前關(guān)聯(lián)好的事件處理器來處理這些事件云矫。
雖然文件事件處理器以單線程方式運(yùn)行, 但通過使用 I/O 多路復(fù)用程序來監(jiān)聽多個(gè)套接字汗菜, 文件事件處理器既實(shí)現(xiàn)了高性能的網(wǎng)絡(luò)通信模型让禀, 又可以很好地與 redis 服務(wù)器中其他同樣以單線程方式運(yùn)行的模塊進(jìn)行對接挑社, 這保持了 Redis 內(nèi)部單線程設(shè)計(jì)的簡單性。
參考:https://www.cnblogs.com/barrywxx/p/8570821.html
事務(wù)
什么是事務(wù)巡揍?
事務(wù)是一個(gè)單獨(dú)的隔離操作:事務(wù)中的所有命令都會序列化痛阻、按順序地執(zhí)行。事務(wù)在執(zhí)行的過程中吼肥,不會被其他客戶端發(fā)送來的命令請求所打斷录平。
事務(wù)是一個(gè)原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行缀皱。
Redis事務(wù)的概念
Redis 事務(wù)的本質(zhì)是通過MULTI斗这、EXEC、WATCH等一組命令的集合啤斗。事務(wù)支持一次執(zhí)行多個(gè)命令表箭,一個(gè)事務(wù)中所有命令都會被序列化。在事務(wù)執(zhí)行過程钮莲,會按照順序串行化執(zhí)行隊(duì)列中的命令免钻,其他客戶端提交的命令請求不會插入到事務(wù)執(zhí)行命令序列中。
總結(jié)說:redis事務(wù)就是一次性崔拥、順序性极舔、排他性的執(zhí)行一個(gè)隊(duì)列中的一系列命令。
Redis事務(wù)的三個(gè)階段
事務(wù)開始 MULTI
命令入隊(duì)
事務(wù)執(zhí)行 EXEC
事務(wù)執(zhí)行過程中链瓦,如果服務(wù)端收到有EXEC拆魏、DISCARD、WATCH慈俯、MULTI之外的請求渤刃,將會把請求放入隊(duì)列中排隊(duì)
Redis事務(wù)相關(guān)命令
Redis事務(wù)功能是通過MULTI、EXEC贴膘、DISCARD和WATCH 四個(gè)原語實(shí)現(xiàn)的
Redis會將一個(gè)事務(wù)中的所有命令序列化卖子,然后按順序執(zhí)行。
redis 不支持回滾刑峡,“Redis 在事務(wù)失敗時(shí)不進(jìn)行回滾洋闽,而是繼續(xù)執(zhí)行余下的命令”, 所以 Redis 的內(nèi)部可以保持簡單且快速突梦。
如果在一個(gè)事務(wù)中的命令出現(xiàn)錯(cuò)誤诫舅,那么所有的命令都不會執(zhí)行;
如果在一個(gè)事務(wù)中出現(xiàn)運(yùn)行錯(cuò)誤阳似,那么正確的命令會被執(zhí)行
WATCH 命令是一個(gè)樂觀鎖,可以為 Redis 事務(wù)提供 check-and-set (CAS)行為铐伴〈樽啵可以監(jiān)控一個(gè)或多個(gè)鍵俏讹,一旦其中有一個(gè)鍵被修改(或刪除),之后的事務(wù)就不會執(zhí)行畜吊,監(jiān)控一直持續(xù)到EXEC命令泽疆。
MULTI命令用于開啟一個(gè)事務(wù),它總是返回OK玲献。MULTI執(zhí)行之后殉疼,客戶端可以繼續(xù)向服務(wù)器發(fā)送任意多條命令,這些命令不會立即被執(zhí)行捌年,而是被放到一個(gè)隊(duì)列中瓢娜,當(dāng)EXEC命令被調(diào)用時(shí),所有隊(duì)列中的命令才會被執(zhí)行礼预。
EXEC:執(zhí)行所有事務(wù)塊內(nèi)的命令眠砾。返回事務(wù)塊內(nèi)所有命令的返回值,按命令執(zhí)行的先后順序排列托酸。當(dāng)操作被打斷時(shí)褒颈,返回空值 nil 。
通過調(diào)用DISCARD励堡,客戶端可以清空事務(wù)隊(duì)列谷丸,并放棄執(zhí)行事務(wù), 并且客戶端會從事務(wù)狀態(tài)中退出应结。
UNWATCH命令可以取消watch對所有key的監(jiān)控刨疼。
事務(wù)管理(ACID)概述
原子性(Atomicity)
原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生摊趾,要么都不發(fā)生币狠。
一致性(Consistency)
事務(wù)前后數(shù)據(jù)的完整性必須保持一致。
隔離性(Isolation)
多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)砾层,一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行
持久性(Durability)
持久性是指一個(gè)事務(wù)一旦被提交漩绵,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對其有任何影響
Redis的事務(wù)總是具有ACID中的一致性和隔離性肛炮,其他特性是不支持的止吐。當(dāng)服務(wù)器運(yùn)行在AOF持久化模式下,并且appendfsync選項(xiàng)的值為always時(shí)侨糟,事務(wù)也具有耐久性碍扔。
Redis事務(wù)支持隔離性嗎
Redis 是單進(jìn)程程序,并且它保證在執(zhí)行事務(wù)時(shí)秕重,不會對事務(wù)進(jìn)行中斷不同,事務(wù)可以運(yùn)行直到執(zhí)行完所有事務(wù)隊(duì)列中的命令為止。因此,Redis 的事務(wù)是總是帶有隔離性的二拐。
Redis事務(wù)保證原子性嗎服鹅,支持回滾嗎
Redis中,單條命令是原子性執(zhí)行的百新,但事務(wù)不保證原子性企软,且沒有回滾。事務(wù)中任意命令執(zhí)行失敗饭望,其余的命令仍會被執(zhí)行仗哨。
Redis事務(wù)其他實(shí)現(xiàn)
基于Lua腳本,Redis可以保證腳本內(nèi)的命令一次性铅辞、按順序地執(zhí)行厌漂,
其同時(shí)也不提供事務(wù)運(yùn)行錯(cuò)誤的回滾,執(zhí)行過程中如果部分命令運(yùn)行錯(cuò)誤巷挥,剩下的命令還是會繼續(xù)運(yùn)行完
基于中間標(biāo)記變量桩卵,通過另外的標(biāo)記變量來標(biāo)識事務(wù)是否執(zhí)行完成,讀取數(shù)據(jù)時(shí)先讀取該標(biāo)記變量判斷是否事務(wù)執(zhí)行完成倍宾。但這樣會需要額外寫代碼實(shí)現(xiàn)雏节,比較繁瑣
集群方案
哨兵模式
哨兵的介紹
sentinel,中文名是哨兵高职。哨兵是 redis 集群機(jī)構(gòu)中非常重要的一個(gè)組件钩乍,主要有以下功能:
集群監(jiān)控:負(fù)責(zé)監(jiān)控 redis master 和 slave 進(jìn)程是否正常工作。
消息通知:如果某個(gè) redis 實(shí)例有故障怔锌,那么哨兵負(fù)責(zé)發(fā)送消息作為報(bào)警通知給管理員寥粹。
故障轉(zhuǎn)移:如果 master node 掛掉了,會自動轉(zhuǎn)移到 slave node 上埃元。
配置中心:如果故障轉(zhuǎn)移發(fā)生了涝涤,通知 client 客戶端新的 master 地址。
哨兵用于實(shí)現(xiàn) redis 集群的高可用岛杀,本身也是分布式的阔拳,作為一個(gè)哨兵集群去運(yùn)行,互相協(xié)同工作类嗤。
故障轉(zhuǎn)移時(shí)糊肠,判斷一個(gè) master node 是否宕機(jī)了,需要大部分的哨兵都同意才行遗锣,涉及到了分布式選舉的問題货裹。
即使部分哨兵節(jié)點(diǎn)掛掉了,哨兵集群還是能正常工作的精偿,因?yàn)槿绻粋€(gè)作為高可用機(jī)制重要組成部分的故障轉(zhuǎn)移系統(tǒng)本身是單點(diǎn)的弧圆,那就很坑爹了赋兵。
哨兵的核心知識
哨兵至少需要 3 個(gè)實(shí)例,來保證自己的健壯性搔预。
哨兵 + redis 主從的部署架構(gòu)毡惜,是不保證數(shù)據(jù)零丟失的,只能保證 redis 集群的高可用性斯撮。
對于哨兵 + redis 主從這種復(fù)雜的部署架構(gòu),盡量在測試環(huán)境和生產(chǎn)環(huán)境扶叉,都進(jìn)行充足的測試和演練勿锅。
官方Redis Cluster 方案(服務(wù)端路由查詢)
edis 集群模式的工作原理能說一下么?在集群模式下枣氧,redis 的 key 是如何尋址的溢十?分布式尋址都有哪些算法?了解一致性 hash 算法嗎达吞?
簡介
Redis Cluster是一種服務(wù)端Sharding技術(shù)张弛,3.0版本開始正式提供。Redis Cluster并沒有使用一致性hash酪劫,而是采用slot(槽)的概念吞鸭,一共分成16384個(gè)槽。將請求發(fā)送到任意節(jié)點(diǎn)覆糟,接收到請求的節(jié)點(diǎn)會將查詢請求發(fā)送到正確的節(jié)點(diǎn)上執(zhí)行
方案說明
通過哈希的方式刻剥,將數(shù)據(jù)分片,每個(gè)節(jié)點(diǎn)均分存儲一定哈希槽(哈希值)區(qū)間的數(shù)據(jù)滩字,默認(rèn)分配了16384 個(gè)槽位
每份數(shù)據(jù)分片會存儲在多個(gè)互為主從的多節(jié)點(diǎn)上
數(shù)據(jù)寫入先寫主節(jié)點(diǎn)造虏,再同步到從節(jié)點(diǎn)(支持配置為阻塞同步)
同一分片多個(gè)節(jié)點(diǎn)間的數(shù)據(jù)不保持一致性
讀取數(shù)據(jù)時(shí),當(dāng)客戶端操作的key沒有分配在該節(jié)點(diǎn)上時(shí)麦箍,redis會返回轉(zhuǎn)向指令漓藕,指向正確的節(jié)點(diǎn)
擴(kuò)容時(shí)時(shí)需要需要把舊節(jié)點(diǎn)的數(shù)據(jù)遷移一部分到新節(jié)點(diǎn)
在 redis cluster 架構(gòu)下,每個(gè) redis 要放開兩個(gè)端口號挟裂,比如一個(gè)是 6379享钞,另外一個(gè)就是 加1w 的端口號,比如 16379话瞧。
16379 端口號是用來進(jìn)行節(jié)點(diǎn)間通信的嫩与,也就是 cluster bus 的東西,cluster bus 的通信交排,用來進(jìn)行故障檢測划滋、配置更新、故障轉(zhuǎn)移授權(quán)埃篓。cluster bus 用了另外一種二進(jìn)制的協(xié)議处坪,gossip 協(xié)議,用于節(jié)點(diǎn)間進(jìn)行高效的數(shù)據(jù)交換,占用更少的網(wǎng)絡(luò)帶寬和處理時(shí)間。
節(jié)點(diǎn)間的內(nèi)部通信機(jī)制
基本通信原理
集群元數(shù)據(jù)的維護(hù)有兩種方式:集中式乐设、Gossip 協(xié)議驹愚。redis cluster 節(jié)點(diǎn)間采用 gossip 協(xié)議進(jìn)行通信。
分布式尋址算法
hash 算法(大量緩存重建)
一致性 hash 算法(自動緩存遷移)+ 虛擬節(jié)點(diǎn)(自動負(fù)載均衡)
redis cluster 的 hash slot 算法
優(yōu)點(diǎn)
無中心架構(gòu)裤纹,支持動態(tài)擴(kuò)容,對業(yè)務(wù)透明
具備Sentinel的監(jiān)控和自動Failover(故障轉(zhuǎn)移)能力
客戶端不需要連接集群所有節(jié)點(diǎn)丧没,連接集群中任何一個(gè)可用節(jié)點(diǎn)即可
高性能鹰椒,客戶端直連redis服務(wù),免去了proxy代理的損耗
缺點(diǎn)
運(yùn)維也很復(fù)雜呕童,數(shù)據(jù)遷移需要人工干預(yù)
只能使用0號數(shù)據(jù)庫
不支持批量操作(pipeline管道操作)
分布式邏輯和存儲模塊耦合等
基于客戶端分配
簡介
Redis Sharding是Redis Cluster出來之前漆际,業(yè)界普遍使用的多Redis實(shí)例集群方法。其主要思想是采用哈希算法將Redis數(shù)據(jù)的key進(jìn)行散列夺饲,通過hash函數(shù)奸汇,特定的key會映射到特定的Redis節(jié)點(diǎn)上。Java redis客戶端驅(qū)動jedis往声,支持Redis Sharding功能擂找,即ShardedJedis以及結(jié)合緩存池的ShardedJedisPool
優(yōu)點(diǎn)
優(yōu)勢在于非常簡單,服務(wù)端的Redis實(shí)例彼此獨(dú)立浩销,相互無關(guān)聯(lián)婴洼,每個(gè)Redis實(shí)例像單服務(wù)器一樣運(yùn)行,非常容易線性擴(kuò)展撼嗓,系統(tǒng)的靈活性很強(qiáng)
缺點(diǎn)
由于sharding處理放到客戶端柬采,規(guī)模進(jìn)一步擴(kuò)大時(shí)給運(yùn)維帶來挑戰(zhàn)。
客戶端sharding不支持動態(tài)增刪節(jié)點(diǎn)且警。服務(wù)端Redis實(shí)例群拓?fù)浣Y(jié)構(gòu)有變化時(shí)粉捻,每個(gè)客戶端都需要更新調(diào)整。連接不能共享斑芜,當(dāng)應(yīng)用規(guī)模增大時(shí)肩刃,資源浪費(fèi)制約優(yōu)化
基于代理服務(wù)器分片
簡介
客戶端發(fā)送請求到一個(gè)代理組件,代理解析客戶端的數(shù)據(jù)杏头,并將請求轉(zhuǎn)發(fā)至正確的節(jié)點(diǎn)盈包,最后將結(jié)果回復(fù)給客戶端
特征
透明接入,業(yè)務(wù)程序不用關(guān)心后端Redis實(shí)例醇王,切換成本低
Proxy 的邏輯和存儲的邏輯是隔離的
代理層多了一次轉(zhuǎn)發(fā)呢燥,性能有所損耗
業(yè)界開源方案
Twtter開源的Twemproxy
豌豆莢開源的Codis
Redis 主從架構(gòu)
單機(jī)的 redis,能夠承載的 QPS 大概就在上萬到幾萬不等寓娩。對于緩存來說叛氨,一般都是用來支撐讀高并發(fā)的呼渣。因此架構(gòu)做成主從(master-slave)架構(gòu),一主多從寞埠,主負(fù)責(zé)寫屁置,并且將數(shù)據(jù)復(fù)制到其它的 slave 節(jié)點(diǎn),從節(jié)點(diǎn)負(fù)責(zé)讀仁连。所有的讀請求全部走從節(jié)點(diǎn)蓝角。這樣也可以很輕松實(shí)現(xiàn)水平擴(kuò)容,支撐讀高并發(fā)饭冬。
redis replication -> 主從架構(gòu) -> 讀寫分離 -> 水平擴(kuò)容支撐讀高并發(fā)
redis replication 的核心機(jī)制
redis 采用異步方式復(fù)制數(shù)據(jù)到 slave 節(jié)點(diǎn)帅容,不過 redis2.8 開始,slave node 會周期性地確認(rèn)自己每次復(fù)制的數(shù)據(jù)量伍伤;
一個(gè) master node 是可以配置多個(gè) slave node 的;
slave node 也可以連接其他的 slave node遣钳;
slave node 做復(fù)制的時(shí)候扰魂,不會 block master node 的正常工作;
slave node 在做復(fù)制的時(shí)候蕴茴,也不會 block 對自己的查詢操作劝评,它會用舊的數(shù)據(jù)集來提供服務(wù);但是復(fù)制完成的時(shí)候倦淀,需要刪除舊數(shù)據(jù)集蒋畜,加載新數(shù)據(jù)集,這個(gè)時(shí)候就會暫停對外服務(wù)了撞叽;
slave node 主要用來進(jìn)行橫向擴(kuò)容姻成,做讀寫分離,擴(kuò)容的 slave node 可以提高讀的吞吐量愿棋。
注意科展,如果采用了主從架構(gòu),那么建議必須開啟 master node 的持久化糠雨,不建議用 slave node 作為 master node 的數(shù)據(jù)熱備才睹,因?yàn)槟菢拥脑挘绻汴P(guān)掉 master 的持久化甘邀,可能在 master 宕機(jī)重啟的時(shí)候數(shù)據(jù)是空的琅攘,然后可能一經(jīng)過復(fù)制, slave node 的數(shù)據(jù)也丟了松邪。
另外坞琴,master 的各種備份方案,也需要做逗抑。萬一本地的所有文件丟失了置济,從備份中挑選一份 rdb 去恢復(fù) master解恰,這樣才能確保啟動的時(shí)候,是有數(shù)據(jù)的浙于,即使采用了后續(xù)講解的高可用機(jī)制护盈,slave node 可以自動接管 master node,但也可能 sentinel 還沒檢測到 master failure羞酗,master node 就自動重啟了腐宋,還是可能導(dǎo)致上面所有的 slave node 數(shù)據(jù)被清空。
redis 主從復(fù)制的核心原理
當(dāng)啟動一個(gè) slave node 的時(shí)候檀轨,它會發(fā)送一個(gè) PSYNC 命令給 master node胸竞。
如果這是 slave node 初次連接到 master node,那么會觸發(fā)一次 full resynchronization 全量復(fù)制参萄。此時(shí) master 會啟動一個(gè)后臺線程卫枝,開始生成一份 RDB 快照文件,
同時(shí)還會將從客戶端 client 新收到的所有寫命令緩存在內(nèi)存中讹挎。RDB 文件生成完畢后校赤, master 會將這個(gè) RDB 發(fā)送給 slave,slave 會先寫入本地磁盤筒溃,然后再從本地磁盤加載到內(nèi)存中马篮,
接著 master 會將內(nèi)存中緩存的寫命令發(fā)送到 slave,slave 也會同步這些數(shù)據(jù)怜奖。
slave node 如果跟 master node 有網(wǎng)絡(luò)故障浑测,斷開了連接,會自動重連歪玲,連接之后 master node 僅會復(fù)制給 slave 部分缺少的數(shù)據(jù)迁央。
過程原理
當(dāng)從庫和主庫建立MS關(guān)系后,會向主數(shù)據(jù)庫發(fā)送SYNC命令
主庫接收到SYNC命令后會開始在后臺保存快照(RDB持久化過程)滥崩,并將期間接收到的寫命令緩存起來
當(dāng)快照完成后漱贱,主Redis會將快照文件和所有緩存的寫命令發(fā)送給從Redis
從Redis接收到后,會載入快照文件并且執(zhí)行收到的緩存的命令
之后夭委,主Redis每當(dāng)接收到寫命令時(shí)就會將命令發(fā)送從Redis幅狮,從而保證數(shù)據(jù)的一致
缺點(diǎn)
所有的slave節(jié)點(diǎn)數(shù)據(jù)的復(fù)制和同步都由master節(jié)點(diǎn)來處理,會照成master節(jié)點(diǎn)壓力太大株灸,使用主從從結(jié)構(gòu)來解決
Redis集群的主從復(fù)制模型是怎樣的崇摄?
為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型慌烧,每個(gè)節(jié)點(diǎn)都會有N-1個(gè)復(fù)制品
生產(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 萬讀寫請求/s。
機(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ī)互捌,都會自動故障遷移,redis 從實(shí)例會自動變成主實(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 左右的請求量。
其實(shí)大型的公司凌唬,會有基礎(chǔ)架構(gòu)的 team 負(fù)責(zé)緩存集群的運(yùn)維并齐。
說說Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念客税,Redis集群有16384個(gè)哈希槽况褪,每個(gè)key通過CRC16校驗(yàn)后對16384取模來決定放置哪個(gè)槽,集群的每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分hash槽更耻。
Redis集群會有寫操作丟失嗎测垛?為什么?
Redis并不能保證數(shù)據(jù)的強(qiáng)一致性秧均,這意味這在實(shí)際中集群在特定的條件下可能會丟失寫操作食侮。
Redis集群之間是如何復(fù)制的号涯?
異步復(fù)制
Redis集群最大節(jié)點(diǎn)個(gè)數(shù)是多少?
16384個(gè)
Redis集群如何選擇數(shù)據(jù)庫锯七?
Redis集群目前無法做數(shù)據(jù)庫選擇链快,默認(rèn)在0數(shù)據(jù)庫。
分區(qū)
Redis是單線程的起胰,如何提高多核CPU的利用率久又?
可以在同一個(gè)服務(wù)器部署多個(gè)Redis的實(shí)例,并把他們當(dāng)作不同的服務(wù)器來使用效五,在某些時(shí)候地消,無論如何一個(gè)服務(wù)器是不夠的, 所以畏妖,如果你想使用多個(gè)CPU脉执,你可以考慮一下分片(shard)。
為什么要做Redis分區(qū)戒劫?
分區(qū)可以讓Redis管理更大的內(nèi)存半夷,Redis將可以使用所有機(jī)器的內(nèi)存。如果沒有分區(qū)迅细,你最多只能使用一臺機(jī)器的內(nèi)存巫橄。分區(qū)使Redis的計(jì)算能力通過簡單地增加計(jì)算機(jī)得到成倍提升,Redis的網(wǎng)絡(luò)帶寬也會隨著計(jì)算機(jī)和網(wǎng)卡的增加而成倍增長茵典。
你知道有哪些Redis分區(qū)實(shí)現(xiàn)方案湘换?
客戶端分區(qū)就是在客戶端就已經(jīng)決定數(shù)據(jù)會被存儲到哪個(gè)redis節(jié)點(diǎn)或者從哪個(gè)redis節(jié)點(diǎn)讀取。大多數(shù)客戶端已經(jīng)實(shí)現(xiàn)了客戶端分區(qū)统阿。
代理分區(qū) 意味著客戶端將請求發(fā)送給代理彩倚,然后代理決定去哪個(gè)節(jié)點(diǎn)寫數(shù)據(jù)或者讀數(shù)據(jù)。代理根據(jù)分區(qū)規(guī)則決定請求哪些Redis實(shí)例扶平,然后根據(jù)Redis的響應(yīng)結(jié)果返回給客戶端帆离。redis和memcached的一種代理實(shí)現(xiàn)就是Twemproxy
查詢路由(Query routing) 的意思是客戶端隨機(jī)地請求任意一個(gè)redis實(shí)例,然后由Redis將請求轉(zhuǎn)發(fā)給正確的Redis節(jié)點(diǎn)结澄。Redis Cluster實(shí)現(xiàn)了一種混合形式的查詢路由哥谷,但并不是直接將請求從一個(gè)redis節(jié)點(diǎn)轉(zhuǎn)發(fā)到另一個(gè)redis節(jié)點(diǎn),而是在客戶端的幫助下直接redirected到正確的redis節(jié)點(diǎn)麻献。
Redis分區(qū)有什么缺點(diǎn)呼巷?
涉及多個(gè)key的操作通常不會被支持。例如你不能對兩個(gè)集合求交集赎瑰,因?yàn)樗麄兛赡鼙淮鎯Φ讲煌腞edis實(shí)例(實(shí)際上這種情況也有辦法王悍,但是不能直接使用交集指令)。
同時(shí)操作多個(gè)key,則不能使用Redis事務(wù).
分區(qū)使用的粒度是key餐曼,不能使用一個(gè)非常長的排序key存儲一個(gè)數(shù)據(jù)集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set)
當(dāng)使用分區(qū)的時(shí)候压储,數(shù)據(jù)處理會非常復(fù)雜鲜漩,例如為了備份你必須從不同的Redis實(shí)例和主機(jī)同時(shí)收集RDB / AOF文件。
分區(qū)時(shí)動態(tài)擴(kuò)容或縮容可能非常復(fù)雜集惋。Redis集群在運(yùn)行時(shí)增加或者刪除Redis節(jié)點(diǎn)孕似,能做到最大程度對用戶透明地?cái)?shù)據(jù)再平衡,但其他一些客戶端分區(qū)或者代理分區(qū)方法則不支持這種特性刮刑。然而喉祭,有一種預(yù)分片的技術(shù)也可以較好的解決這個(gè)問題。
分布式問題
Redis實(shí)現(xiàn)分布式鎖
Redis為單進(jìn)程單線程模式雷绢,采用隊(duì)列模式將并發(fā)訪問變成串行訪問泛烙,且多客戶端對Redis的連接并不存在競爭關(guān)系Redis中可以使用SETNX命令實(shí)現(xiàn)分布式鎖。
當(dāng)且僅當(dāng) key 不存在翘紊,將 key 的值設(shè)為 value蔽氨。若給定的 key 已經(jīng)存在,則 SETNX 不做任何動作
SETNX 是『SET if Not eXists』(如果不存在帆疟,則 SET)的簡寫鹉究。
返回值:設(shè)置成功,返回 1 踪宠。設(shè)置失敗自赔,返回 0 。
使用SETNX完成同步鎖的流程及事項(xiàng)如下:
使用SETNX命令獲取鎖柳琢,若返回0(key已存在绍妨,鎖已存在)則獲取失敗,反之獲取成功
為了防止獲取鎖后程序出現(xiàn)異常染厅,導(dǎo)致其他線程/進(jìn)程調(diào)用SETNX命令總是返回0而進(jìn)入死鎖狀態(tài)痘绎,需要為該key設(shè)置一個(gè)“合理”的過期時(shí)間
釋放鎖津函,使用DEL命令將鎖數(shù)據(jù)刪除
如何解決 Redis 的并發(fā)競爭 Key 問題
所謂 Redis 的并發(fā)競爭 Key 的問題也就是多個(gè)系統(tǒng)同時(shí)對一個(gè) key 進(jìn)行操作肖粮,但是最后執(zhí)行的順序和我們期望的順序不同,這樣也就導(dǎo)致了結(jié)果的不同尔苦!
推薦一種方案:分布式鎖(zookeeper 和 redis 都可以實(shí)現(xiàn)分布式鎖)涩馆。(如果不存在 Redis 的并發(fā)競爭 Key 問題,不要使用分布式鎖允坚,這樣會影響性能)
基于zookeeper臨時(shí)有序節(jié)點(diǎn)可以實(shí)現(xiàn)的分布式鎖魂那。大致思想為:每個(gè)客戶端對某個(gè)方法加鎖時(shí),在zookeeper上的與該方法對應(yīng)的指定節(jié)點(diǎn)的目錄下稠项,生成一個(gè)唯一的瞬時(shí)有序節(jié)點(diǎn)涯雅。判斷是否獲取鎖的方式很簡單,只需要判斷有序節(jié)點(diǎn)中序號最小的一個(gè)展运。當(dāng)釋放鎖的時(shí)候活逆,只需將這個(gè)瞬時(shí)節(jié)點(diǎn)刪除即可精刷。同時(shí),其可以避免服務(wù)宕機(jī)導(dǎo)致的鎖無法釋放蔗候,而產(chǎn)生的死鎖問題怒允。完成業(yè)務(wù)流程后,刪除對應(yīng)的子節(jié)點(diǎn)釋放鎖锈遥。
在實(shí)踐中纫事,當(dāng)然是從以可靠性為主。所以首推Zookeeper所灸。
參考:http://www.reibang.com/p/8bddd381de06
分布式Redis是前期做還是后期規(guī)模上來了再做好丽惶?為什么?
既然Redis是如此的輕量(單實(shí)例只使用1M內(nèi)存)庆寺,為防止以后的擴(kuò)容蚊夫,最好的辦法就是一開始就啟動較多實(shí)例。即便你只有一臺服務(wù)器懦尝,你也可以一開始就讓Redis以分布式的方式運(yùn)行知纷,使用分區(qū),在同一臺服務(wù)器上啟動多個(gè)實(shí)例陵霉。
一開始就多設(shè)置幾個(gè)Redis實(shí)例琅轧,例如32或者64個(gè)實(shí)例,對大多數(shù)用戶來說這操作起來可能比較麻煩踊挠,但是從長久來看做這點(diǎn)犧牲是值得的乍桂。
這樣的話,當(dāng)你的數(shù)據(jù)不斷增長效床,需要更多的Redis服務(wù)器時(shí)睹酌,你需要做的就是僅僅將Redis實(shí)例從一臺服務(wù)遷移到另外一臺服務(wù)器而已(而不用考慮重新分區(qū)的問題)。一旦你添加了另一臺服務(wù)器剩檀,你需要將你一半的Redis實(shí)例從第一臺機(jī)器遷移到第二臺機(jī)器憋沿。
什么是 RedLock
Redis 官方站提出了一種權(quán)威的基于 Redis 實(shí)現(xiàn)分布式鎖的方式名叫 Redlock,此種方式比原先的單節(jié)點(diǎn)的方法更安全沪猴。它可以保證以下特性:
安全特性:互斥訪問辐啄,即永遠(yuǎn)只有一個(gè) client 能拿到鎖
避免死鎖:最終 client 都可能拿到鎖,不會出現(xiàn)死鎖的情況运嗜,即使原本鎖住某資源的 client crash 了或者出現(xiàn)了網(wǎng)絡(luò)分區(qū)
容錯(cuò)性:只要大部分 Redis 節(jié)點(diǎn)存活就可以正常提供服務(wù)
緩存異常
緩存雪崩
緩存雪崩是指緩存同一時(shí)間大面積的失效壶辜,所以,后面的請求都會落到數(shù)據(jù)庫上担租,造成數(shù)據(jù)庫短時(shí)間內(nèi)承受大量請求而崩掉砸民。
解決方案
緩存數(shù)據(jù)的過期時(shí)間設(shè)置隨機(jī),防止同一時(shí)間大量數(shù)據(jù)過期現(xiàn)象發(fā)生。
一般并發(fā)量不是特別多的時(shí)候岭参,使用最多的解決方案是加鎖排隊(duì)便贵。
給每一個(gè)緩存數(shù)據(jù)增加相應(yīng)的緩存標(biāo)記,記錄緩存的是否失效冗荸,如果緩存標(biāo)記失效承璃,則更新數(shù)據(jù)緩存。
緩存穿透
緩存穿透是指緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù)蚌本,導(dǎo)致所有的請求都落到數(shù)據(jù)庫上盔粹,造成數(shù)據(jù)庫短時(shí)間內(nèi)承受大量請求而崩掉。
解決方案
接口層增加校驗(yàn)程癌,如用戶鑒權(quán)校驗(yàn)舷嗡,id做基礎(chǔ)校驗(yàn),id<=0的直接攔截嵌莉;
從緩存取不到的數(shù)據(jù)进萄,在數(shù)據(jù)庫中也沒有取到,這時(shí)也可以將key-value對寫為key-null锐峭,緩存有效時(shí)間可以設(shè)置短點(diǎn)中鼠,如30秒(設(shè)置太長會導(dǎo)致正常情況也沒法使用)。這樣可以防止攻擊用戶反復(fù)用同一個(gè)id暴力攻擊
采用布隆過濾器沿癞,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的 bitmap 中援雇,一個(gè)一定不存在的數(shù)據(jù)會被這個(gè) bitmap 攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力
附加
對于空間的利用到達(dá)了一種極致椎扬,那就是Bitmap和布隆過濾器(Bloom Filter)惫搏。
Bitmap:典型的就是哈希表
缺點(diǎn)是,Bitmap對于每個(gè)元素只能記錄1bit信息蚕涤,如果還想完成額外的功能筐赔,恐怕只能靠犧牲更多的空間、時(shí)間來完成了揖铜。
布隆過濾器(推薦)
就是引入了k(k>1)k(k>1)個(gè)相互獨(dú)立的哈希函數(shù)茴丰,保證在給定的空間、誤判率下蛮位,完成元素判重的過程较沪。
它的優(yōu)點(diǎn)是空間效率和查詢時(shí)間都遠(yuǎn)遠(yuǎn)超過一般的算法鳞绕,缺點(diǎn)是有一定的誤識別率和刪除困難失仁。
Bloom-Filter算法的核心思想就是利用多個(gè)不同的Hash函數(shù)來解決“沖突”。
Hash存在一個(gè)沖突(碰撞)的問題们何,用同一個(gè)Hash得到的兩個(gè)URL的值有可能相同萄焦。為了減少沖突,我們可以多引入幾個(gè)Hash,如果通過其中的一個(gè)Hash值我們得出某元素不在集合中拂封,那么該元素肯定不在集合中茬射。只有在所有的Hash函數(shù)告訴我們該元素在集合中時(shí),才能確定該元素存在于集合中冒签。這便是Bloom-Filter的基本思想在抛。
Bloom-Filter一般用于在大數(shù)據(jù)量的集合中判定某元素是否存在。
緩存擊穿
緩存擊穿是指緩存中沒有但數(shù)據(jù)庫中有的數(shù)據(jù)(一般是緩存時(shí)間到期)萧恕,這時(shí)由于并發(fā)用戶特別多刚梭,同時(shí)讀緩存沒讀到數(shù)據(jù),又同時(shí)去數(shù)據(jù)庫去取數(shù)據(jù)票唆,引起數(shù)據(jù)庫壓力瞬間增大朴读,造成過大壓力。和緩存雪崩不同的是走趋,緩存擊穿指并發(fā)查同一條數(shù)據(jù)衅金,緩存雪崩是不同數(shù)據(jù)都過期了,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫簿煌。
解決方案
設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過期氮唯。
加互斥鎖姨伟,互斥鎖
緩存預(yù)熱
緩存預(yù)熱就是系統(tǒng)上線后,將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)琳水。這樣就可以避免在用戶請求的時(shí)候,先查詢數(shù)據(jù)庫般堆,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)私沮!
解決方案
直接寫個(gè)緩存刷新頁面,上線時(shí)手工操作一下和橙;
數(shù)據(jù)量不大,可以在項(xiàng)目啟動的時(shí)候自動進(jìn)行加載魔招;
定時(shí)刷新緩存办斑;
緩存降級
當(dāng)訪問量劇增、服務(wù)出現(xiàn)問題(如響應(yīng)時(shí)間慢或不響應(yīng))或非核心服務(wù)影響到核心流程的性能時(shí)鳞疲,仍然需要保證服務(wù)還是可用的尚洽,即使是有損服務(wù)。系統(tǒng)可以根據(jù)一些關(guān)鍵數(shù)據(jù)進(jìn)行自動降級橄维,也可以配置開關(guān)實(shí)現(xiàn)人工降級争舞。
緩存降級的最終目的是保證核心服務(wù)可用澈灼,即使是有損的叁熔。而且有些服務(wù)是無法降級的(如加入購物車、結(jié)算)荣回。
在進(jìn)行降級之前要對系統(tǒng)進(jìn)行梳理心软,看看系統(tǒng)是不是可以丟卒保帥删铃;從而梳理出哪些必須誓死保護(hù),哪些可降級咒劲;比如可以參考日志級別設(shè)置預(yù)案:
一般:比如有些服務(wù)偶爾因?yàn)榫W(wǎng)絡(luò)抖動或者服務(wù)正在上線而超時(shí)腐魂,可以自動降級蛔屹;
警告:有些服務(wù)在一段時(shí)間內(nèi)成功率有波動(如在95~100%之間)风题,可以自動降級或人工降級沛硅,并發(fā)送告警摇肌;
錯(cuò)誤:比如可用率低于90%,或者數(shù)據(jù)庫連接池被打爆了昵骤,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值变秦,此時(shí)可以根據(jù)情況自動降級或者人工降級蹦玫;
嚴(yán)重錯(cuò)誤:比如因?yàn)樘厥庠驍?shù)據(jù)錯(cuò)誤了樱溉,此時(shí)需要緊急人工降級纬凤。
服務(wù)降級的目的停士,是為了防止Redis服務(wù)故障恋技,導(dǎo)致數(shù)據(jù)庫跟著一起發(fā)生雪崩問題猖任。因此,對于不重要的緩存數(shù)據(jù)刁赖,可以采取服務(wù)降級策略宇弛,例如一個(gè)比較常見的做法就是枪芒,Redis出現(xiàn)問題,不去數(shù)據(jù)庫查詢纽甘,而是直接返回默認(rèn)值給用戶悍赢。
熱點(diǎn)數(shù)據(jù)和冷數(shù)據(jù)
熱點(diǎn)數(shù)據(jù)左权,緩存才有價(jià)值
對于冷數(shù)據(jù)而言痴颊,大部分?jǐn)?shù)據(jù)可能還沒有再次訪問到就已經(jīng)被擠出內(nèi)存蠢棱,不僅占用內(nèi)存裳扯,而且價(jià)值不大饰豺。頻繁修改的數(shù)據(jù)冤吨,看情況考慮使用緩存
對于熱點(diǎn)數(shù)據(jù),比如我們的某IM產(chǎn)品垒探,生日祝福模塊圾叼,當(dāng)天的壽星列表夷蚊,緩存以后可能讀取數(shù)十萬次惕鼓。再舉個(gè)例子唐础,某導(dǎo)航產(chǎn)品,我們將導(dǎo)航信息洒沦,緩存以后可能讀取數(shù)百萬次微谓。
數(shù)據(jù)更新前至少讀取兩次,緩存才有意義买乃。這個(gè)是最基本的策略剪验,如果緩存還沒有起作用就失效了前联,那就沒有太大價(jià)值了似嗤。
那存不存在烁落,修改頻率很高伤塌,但是又不得不考慮緩存的場景呢每聪?有药薯!比如,這個(gè)讀取接口對數(shù)據(jù)庫的壓力很大诊笤,但是又是熱點(diǎn)數(shù)據(jù)讨跟,這個(gè)時(shí)候就需要考慮通過緩存手段晾匠,減少數(shù)據(jù)庫的壓力凉馆,比如我們的某助手產(chǎn)品的澜共,點(diǎn)贊數(shù)嗦董,收藏?cái)?shù)京革,分享數(shù)等是非常典型的熱點(diǎn)數(shù)據(jù)匹摇,但是又不斷變化,此時(shí)就需要將數(shù)據(jù)同步保存到Redis緩存廊勃,減少數(shù)據(jù)庫壓力供搀。
緩存熱點(diǎn)key
緩存中的一個(gè)Key(比如一個(gè)促銷商品)葛虐,在某個(gè)時(shí)間點(diǎn)過期的時(shí)候屿脐,恰好在這個(gè)時(shí)間點(diǎn)對這個(gè)Key有大量的并發(fā)請求過來的诵,這些請求發(fā)現(xiàn)緩存過期一般都會從后端DB加載數(shù)據(jù)并回設(shè)到緩存西疤,這個(gè)時(shí)候大并發(fā)的請求可能會瞬間把后端DB壓垮。
解決方案
對緩存查詢加鎖兽掰,如果KEY不存在孽尽,就加鎖杉女,然后查DB入緩存熏挎,然后解鎖婆瓜;其他進(jìn)程如果發(fā)現(xiàn)有鎖就等待,然后等解鎖后返回?cái)?shù)據(jù)或者進(jìn)入DB查詢
常用工具
Redis支持的Java客戶端都有哪些乖寒?官方推薦用哪個(gè)楣嘁?
Redisson逐虚、Jedis叭爱、lettuce等等买雾,官方推薦使用Redisson漓穿。
Redis和Redisson有什么關(guān)系晃危?
Redisson是一個(gè)高級的分布式協(xié)調(diào)Redis客服端僚饭,能幫助用戶在分布式環(huán)境中輕松實(shí)現(xiàn)一些Java的對象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)浪慌。
Jedis與Redisson對比有什么優(yōu)缺點(diǎn)权纤?
Jedis是Redis的Java實(shí)現(xiàn)的客戶端汹想,其API提供了比較全面的Redis命令的支持古掏;Redisson實(shí)現(xiàn)了分布式和可擴(kuò)展的Java數(shù)據(jù)結(jié)構(gòu)丧枪,和Jedis相比拧烦,功能較為簡單钝计,不支持字符串操作债沮,不支持排序疫衩、事務(wù)隧土、管道曹傀、分區(qū)等Redis特性皆愉。Redisson的宗旨是促進(jìn)使用者對Redis的關(guān)注分離苞氮,從而讓使用者能夠?qū)⒕Ω械胤旁谔幚順I(yè)務(wù)邏輯上。
其他問題
Redis與Memcached的區(qū)別
兩者都是非關(guān)系型內(nèi)存鍵值數(shù)據(jù)庫奸笤,現(xiàn)在公司一般都是用 Redis 來實(shí)現(xiàn)緩存,而且 Redis 自身也越來越強(qiáng)大了殴瘦!Redis 與 Memcached 主要有以下不同:
(1) memcached所有的值均是簡單的字符串蚪腋,redis作為其替代者屉凯,支持更為豐富的數(shù)據(jù)類型
(2) redis的速度比memcached快很多
(3) redis可以持久化其數(shù)據(jù)
如何保證緩存與數(shù)據(jù)庫雙寫時(shí)的數(shù)據(jù)一致性厘惦?
你只要用緩存宵蕉,就可能會涉及到緩存與數(shù)據(jù)庫雙存儲雙寫羡玛,你只要是雙寫稼稿,就一定會有數(shù)據(jù)一致性的問題让歼,那么你如何解決一致性問題硬猫?
一般來說啸蜜,就是如果你的系統(tǒng)不是嚴(yán)格要求緩存+數(shù)據(jù)庫必須一致性的話衬横,緩存可以稍微的跟數(shù)據(jù)庫偶爾有不一致的情況蜂林,最好不要做這個(gè)方案突那,讀請求和寫請求串行化愕难,串到一個(gè)內(nèi)存隊(duì)列里去猫缭,這樣就可以保證一定不會出現(xiàn)不一致的情況
串行化之后猜丹,就會導(dǎo)致系統(tǒng)的吞吐量會大幅度的降低,用比正常情況下多幾倍的機(jī)器去支撐線上的一個(gè)請求脉顿。
還有一種方式就是可能會暫時(shí)產(chǎn)生不一致的情況艾疟,但是發(fā)生的幾率特別小蔽莱,就是先更新數(shù)據(jù)庫盗冷,然后再刪除緩存正塌。
Redis常見性能問題和解決方案帜羊?
Master最好不要做任何持久化工作,包括內(nèi)存快照和AOF日志文件奶段,特別是不要啟用內(nèi)存快照做持久化剥纷。
如果數(shù)據(jù)比較關(guān)鍵痹籍,某個(gè)Slave開啟AOF備份數(shù)據(jù),策略為每秒同步一次晦鞋。
為了主從復(fù)制的速度和連接的穩(wěn)定性蹲缠,Slave和Master最好在同一個(gè)局域網(wǎng)內(nèi)。
盡量避免在壓力較大的主庫上增加從庫
Master調(diào)用BGREWRITEAOF重寫AOF文件悠垛,AOF在重寫的時(shí)候會占大量的CPU和內(nèi)存資源,導(dǎo)致服務(wù)load過高确买,出現(xiàn)短暫服務(wù)暫徒锛ィ現(xiàn)象。
為了Master的穩(wěn)定性湾趾,主從復(fù)制不要用圖狀結(jié)構(gòu)芭商,用單向鏈表結(jié)構(gòu)更穩(wěn)定,即主從關(guān)系為:Master<–Slave1<–Slave2<–Slave3…撑帖,這樣的結(jié)構(gòu)也方便解決單點(diǎn)故障問題蓉坎,實(shí)現(xiàn)Slave對Master的替換,也即胡嘿,如果Master掛了,可以立馬啟用Slave1做Master钳踊,其他不變衷敌。
Redis官方為什么不提供Windows版本?
因?yàn)槟壳癓inux版本已經(jīng)相當(dāng)穩(wěn)定拓瞪,而且用戶量很大缴罗,無需開發(fā)windows版本,反而會帶來兼容性等問題祭埂。
一個(gè)字符串類型的值能存儲最大容量是多少面氓?
512M
Redis如何做大量數(shù)據(jù)插入兵钮?
Redis2.6開始redis-cli支持一種新的被稱之為pipe mode的新模式用于執(zhí)行大量數(shù)據(jù)插入工作。
假如Redis里面有1億個(gè)key舌界,其中有10w個(gè)key是以某個(gè)固定的已知的前綴開頭的掘譬,如果將它們?nèi)空页鰜恚?/b>
使用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做過異步隊(duì)列嗎笤成,是如何實(shí)現(xiàn)的
使用list類型保存數(shù)據(jù)信息评架,rpush生產(chǎn)消息,lpop消費(fèi)消息炕泳,當(dāng)lpop沒有消息時(shí)纵诞,可以sleep一段時(shí)間,然后再檢查有沒有信息培遵,如果不想sleep的話浙芙,可以使用blpop, 在沒有信息的時(shí)候,會一直阻塞籽腕,直到信息的到來嗡呼。redis可以通過pub/sub主題訂閱模式實(shí)現(xiàn)一個(gè)生產(chǎn)者,多個(gè)消費(fèi)者皇耗,當(dāng)然也存在一定的缺點(diǎn)南窗,當(dāng)消費(fèi)者下線時(shí),生產(chǎn)的消息會丟失郎楼。
Redis如何實(shí)現(xiàn)延時(shí)隊(duì)列
使用sortedset万伤,使用時(shí)間戳做score, 消息內(nèi)容作為key,調(diào)用zadd來生產(chǎn)消息,消費(fèi)者使用zrangbyscore獲取n秒之前的數(shù)據(jù)做輪詢處理敌买。
Redis回收進(jìn)程如何工作的?
一個(gè)客戶端運(yùn)行了新的命令阶界,添加了新的數(shù)據(jù)虹钮。
Redis檢查內(nèi)存使用情況聋庵,如果大于maxmemory的限制, 則根據(jù)設(shè)定好的策略進(jìn)行回收芙粱。
一個(gè)新的命令被執(zhí)行祭玉,等等。
所以我們不斷地穿越內(nèi)存限制的邊界宅倒,通過不斷達(dá)到邊界然后不斷地回收回到邊界以下攘宙。
如果一個(gè)命令的結(jié)果導(dǎo)致大量內(nèi)存被使用(例如很大的集合的交集保存到一個(gè)新的鍵),不用多久內(nèi)存限制就會被這個(gè)內(nèi)存使用量超越拐迁。