目前Redis在互聯(lián)網(wǎng)行業(yè)技術(shù)存儲方面使用廣泛驱入,幾乎所有后端技術(shù)面試官都會在Redis的使用和原理方面對求職者提一些問題赤炒。本篇通俗易懂的整理總結(jié)了近年來針對Redis緩存的相關(guān)面試題并附有相關(guān)的答案氯析,希望大家在以后面試中能夠順利的拿到OFFER。
什么是Redis莺褒?
Redis全稱Remote Dictionary Server掩缓,是一個完全開源免費的,遵守BSD協(xié)議遵岩,使用ANSI C語言編寫你辣、支持網(wǎng)絡(luò)、可基于內(nèi)存亦可持久化的日志型尘执、Key-Value數(shù)據(jù)庫舍哄。它是當(dāng)前最熱門的NoSql非關(guān)系型數(shù)據(jù)庫之一,也被人們稱為數(shù)據(jù)結(jié)構(gòu)服務(wù)器誊锭。
Redis的數(shù)據(jù)類型有哪些蠢熄?
Redis支持五種數(shù)據(jù)類型:string(字符串),hash(哈希)炉旷,list(列表),set(集合)及zset(sorted set:有序集合)叉讥。
1窘行、String(字符串)
string是redis最基本的類型,可以理解成與Memcached一樣的類型图仓,一個key對應(yīng)一個value罐盔。常用命令包括set、get救崔、decr惶看、incr、mget等六孵,一個鍵最大存儲512B纬黎。
應(yīng)用場景:string類型是二進制安全的,通俗的說就是redis的string可以包含任何數(shù)據(jù)劫窒。如jpg圖片或者序列化對象本今。
2、Hash(哈希)
hash是一個鍵值(key=>value)對集合主巍;是string類型的field和value的映射表冠息,hash適合用于存儲對象。常用命令包括hget孕索、hset逛艰、hgetall等,每個hash可以存儲232 -1鍵值對(40多億)搞旭。
應(yīng)用場景:存儲一些結(jié)構(gòu)化的數(shù)據(jù)散怖,比如用戶的昵稱菇绵、年齡、性別杭抠、積分等脸甘,存儲一個用戶信息對象數(shù)據(jù)。
3偏灿、List(列表)
list是按照插入順序排序丹诀,可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。常用命令包括lpush翁垂、rpush铆遭、lpop、rpop沿猜、lrange等枚荣,最多可存儲232 - 1元素(4294967295,每個列表可存儲40多億)啼肩。
應(yīng)用場景:list類型常被用于消息隊列的服務(wù)橄妆,以完成多程序之間的消息交換。
4祈坠、Set(集合)
set是string類型的無序集合害碾,類似list列表一樣,在執(zhí)行插入赦拘、刪除和判斷是否存在某元素時慌随,效率很高。常用命令包括sadd躺同、spop阁猜、smembers、sunion等蹋艺,set包含最大元素數(shù)量是4294967295剃袍。集合是通過哈希表實現(xiàn)的,所以添加车海,刪除笛园,查找的復(fù)雜度都是O(1)。
集合最大的優(yōu)勢在于可以進行交集并集和差集操作侍芝,集合中最大的成員數(shù)為 232 - 1(4294967295, 每個集合可存儲40多億個成員)研铆。
應(yīng)用場景:利用交集求共同數(shù)據(jù);利用唯一性州叠,可以統(tǒng)計訪問網(wǎng)站的所有獨立IP棵红;好友推薦時可根據(jù)tag求交集,大于某個threshold(臨界值的)就可以推薦咧栗。
5逆甜、zset(sorted set:有序集合)
zset和set一樣也是string類型元素的集合虱肄,且不允許重復(fù)的成員。不同的是每個元素都會關(guān)聯(lián)一個double類型的分?jǐn)?shù)(score)交煞,zset的成員是唯一的咏窿,但分?jǐn)?shù)卻可以重復(fù)。redis正是通過分?jǐn)?shù)來為集合中的成員進行從小到大的排序素征。
sorted set是插入有序的集嵌,即自動排序。常用命令包括zadd御毅、zrange根欧、zrem、zcard等端蛆,當(dāng)需要一個有序的并且不重復(fù)的集合列表時凤粗,可以選擇sorted set數(shù)據(jù)結(jié)構(gòu)。
應(yīng)用場景:如存儲全班同學(xué)的成績今豆,其集合value可以是同學(xué)的學(xué)號嫌拣,而score就可以是成績;排行榜應(yīng)用呆躲,根據(jù)得分列出topN的用戶等亭罪。
Redis有什么優(yōu)點?
1)速度快:數(shù)據(jù)存在內(nèi)存中歼秽,類似于HashMap,HashMap的優(yōu)勢就是查找和操作的時間復(fù)雜度都是O(1)情组。
2)支持豐富數(shù)據(jù)類型:包括string燥筷、list、set院崇、Zset肆氓、hash等數(shù)據(jù)類型。
3)持久化存儲:提供RDB和AOF兩種數(shù)據(jù)的持久化存儲方案底瓣,解決內(nèi)存數(shù)據(jù)庫最擔(dān)心的萬一Redis掛掉谢揪,數(shù)據(jù)會消失掉。
4)豐富的特性:可用于訂閱發(fā)布Pub/Sub功能捐凭,事務(wù)拨扶,緩存,消息茁肠,Key過期策略患民,支持多個DB,計數(shù)等垦梆。
Redis有什么缺點匹颤?
1)由于Redis是內(nèi)存數(shù)據(jù)庫仅孩,單臺機器的存儲數(shù)據(jù)量跟機器本身的內(nèi)存大小有關(guān),雖然Redis本身有Key過期策略印蓖,但是還是需要提前預(yù)估和節(jié)約內(nèi)存辽慕。若內(nèi)存增長過快,需要定期刪除數(shù)據(jù)赦肃〗︱龋可以使用Redis Cluster、Codis等方案,對Redis進行分區(qū),從單機Redis變成集群Redis负溪。
2)如果進行完整重同步時由于需要生成RDB文件宙帝,并進行傳輸,會占用主機的CPU税课,并會消耗網(wǎng)絡(luò)的帶寬。不過Redis2.8版本,已經(jīng)有部分重同步的功能琐鲁,但是還是有可能有完整重同步的。如新上線的備機人灼。
3)修改配置文件需要重啟時Redis會將硬盤中的數(shù)據(jù)加載進內(nèi)存围段,比較耗時,在這個過程中Redis是不能提供服務(wù)的投放。
Redis相比memcached有哪些優(yōu)勢奈泪?
1)memcached所有的值均是簡單的字符串,redis作為其替代者灸芳,支持更為豐富的數(shù)據(jù)類型涝桅;
2)redis的速度比memcached快很多;
3)redis可以持久化其數(shù)據(jù)烙样;
4)Redis支持?jǐn)?shù)據(jù)的備份冯遂,即master-slave模式的數(shù)據(jù)備份;
5)使用底層模型不同谒获,它們之間底層實現(xiàn)方式 以及與客戶端之間通信的應(yīng)用協(xié)議不一樣蛤肌。Redis直接自己構(gòu)建了VM 機制 ,因為一般的系統(tǒng)調(diào)用系統(tǒng)函數(shù)的話批狱,會浪費一定的時間去移動和請求裸准;
6)value大小:redis最大可以達到1GB赔硫,而memcache只有1MB狼速。
Redis和memcached有哪些區(qū)別?
1)memecache把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會掛掉向胡,數(shù)據(jù)不能超過內(nèi)存大小恼蓬。
2)redis和memcache都是將數(shù)據(jù)存放在內(nèi)存中,都是內(nèi)存數(shù)據(jù)庫僵芹。
3)redis不僅僅支持簡單的k/v類型的數(shù)據(jù)处硬,同時還提供list,set拇派,hash等數(shù)據(jù)結(jié)構(gòu)的存儲荷辕。?
4)虛擬內(nèi)存–redis當(dāng)物理內(nèi)存用完時,可以將一些很久沒用到的value交換到磁盤件豌,這樣能保證數(shù)據(jù)的持久性疮方。
5)過期策略–memcache在set時就指定,例如set key1 0 0 8,即永不過期茧彤。Redis可以通過例如expire 設(shè)定骡显,例如expire name 10?
6)分布式–設(shè)定memcache集群,利用magent做一主多從曾掂;redis可以做一主多從惫谤。都可以一主一從。
7)存儲數(shù)據(jù)安全–memcache掛掉后珠洗,數(shù)據(jù)若超過內(nèi)存大小溜歪,會丟失數(shù)據(jù);redis可以定期保存到磁盤(持久化)许蓖。
8)災(zāi)難恢復(fù)–memcache掛掉后蝴猪,數(shù)據(jù)不可恢復(fù); redis數(shù)據(jù)丟失后可以通過aof恢復(fù)。
9)Redis支持?jǐn)?shù)據(jù)的備份膊爪,即master-slave模式的數(shù)據(jù)備份拯腮。
*注:“Redis相比memcached有哪些優(yōu)勢?”和“Redis和memcached有哪些區(qū)別蚁飒?”兩者可相互借鑒。
Redis是否是單進程單線程方式萝喘,為什么淮逻?
Redis是單進程單線程的,Redis采用的是基于內(nèi)存的采用的是單進程單線程模型的KV數(shù)據(jù)庫阁簸,由C語言編寫爬早。官方提供的數(shù)據(jù)是可以達到100000+的qps。
Redis處理效率快的原因有幾方面:完全基于內(nèi)存启妹;數(shù)據(jù)結(jié)構(gòu)簡單筛严,對數(shù)據(jù)操作也簡單;使用多路I/O復(fù)用模型饶米。
單進程單線程好處:代碼更清晰桨啃,處理邏輯更簡單车胡;不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作照瘾,沒有因為可能出現(xiàn)死鎖而導(dǎo)致的性能消耗匈棘;不存在多進程或者多線程導(dǎo)致的切換而消耗CPU。
單進程單線程弊端:無法發(fā)揮多核CPU性能析命,不過可以通過在單機開多個Redis實例來完善主卫。
Redis持久化有哪幾種方式?都有什么優(yōu)缺點鹃愤?
redis提供兩種持久化機制RDB和AOF機制簇搅,RDB持久化機制是對redis中的數(shù)據(jù)執(zhí)行周期性的持久化,APF機制對每條寫入命令作為日志软吐,以append-only的模式寫入一個日志文件中瘩将,在redis重啟的時候,可以通過回放AOF日志中的寫入指令來重新構(gòu)建整個數(shù)據(jù)集关噪。
RDB(Redis DataBase)持久化方式:是指用數(shù)據(jù)集快照的方式半持久化模式鸟蟹,記錄redis數(shù)據(jù)庫的所有鍵值對,在某個時間點將數(shù)據(jù)寫入一個臨時文件使兔。持久化結(jié)束后建钥,用這個臨時文件替換上次持久化的文件,達到數(shù)據(jù)恢復(fù)虐沥。
優(yōu)點:
1)只有一個文件dump.rdb熊经,方便持久化。
2)容災(zāi)性好欲险,一個文件可以保存到安全的磁盤镐依。
3)性能最大化,fork子進程來完成寫操作天试,讓主進程繼續(xù)處理命令槐壳,所以是IO最大化。使用單獨子進程來進行持久化喜每,主進程不會進行任何IO操作务唐,保證了redis的高性能。
4)相對于數(shù)據(jù)集大時带兜,比AOF的啟動效率更高枫笛。
缺點:
1)數(shù)據(jù)安全性低。RDB是間隔一段時間進行持久化刚照,如果持久化之間redis發(fā)生 故障刑巧,會發(fā)生數(shù)據(jù)丟失。
AOF(Append-only file)持久化方式:是指所有的命令行記錄以redis命令請 求協(xié)議的格式完全持久化存儲)保存為aof文件。
優(yōu)點:
1)數(shù)據(jù)安全啊楚,aof持久化可以配置appendfsync屬性吠冤,有always,每進行一次 命令操作就記錄到aof文件中一次特幔。
2)通過append模式寫文件咨演,即使中途服務(wù)器宕機,可以通過redis-check-aof工具解決數(shù)據(jù)一致性問題蚯斯。
3)AOF機制的rewrite模式薄风。AOF文件沒被rewrite之前(文件過大時會對命令 進行合并重寫),可以刪除其中的某些命令(比如誤操作的flushall)拍嵌。
缺點:
1)AOF文件比RDB文件大遭赂,且恢復(fù)速度慢。
2)數(shù)據(jù)量大的時候横辆,比RDB啟動效率低撇他。
Redis常見的性能問題和解決方法
1)Master最好不要做任何持久化工作,包括內(nèi)存快照和AOF日志文件狈蚤,特別是不要啟用內(nèi)存快照做持久化困肩。
2)如果數(shù)據(jù)比較關(guān)鍵,某個Slave開啟AOF備份數(shù)據(jù)脆侮,策略為每秒同步一次锌畸。
3)為了主從復(fù)制的速度和連接的穩(wěn)定性,Slave和Master最好在同一個局域網(wǎng)內(nèi)靖避。
4)盡量避免在壓力較大的主庫上增加從庫潭枣。
5)為了Master的穩(wěn)定性,主從復(fù)制不要用圖狀結(jié)構(gòu)幻捏,用單向鏈表結(jié)構(gòu)更穩(wěn)定盆犁,即主從關(guān)系為:Master<--Slave1<--Slave2<--Slave3.......,這樣的結(jié)構(gòu)也方便解決單點故障問題篡九,實現(xiàn)Slave對Master的替換谐岁,也即,如果Master掛了榛臼,可以立馬啟用Slave1做Master伊佃,其他不變。關(guān)注微信公眾號“Java精選”讽坏,每天推送優(yōu)質(zhì)文章。
Redis內(nèi)存回收策略(淘汰策略)例证?
Redis也會因為內(nèi)存不足而出錯路呜,也可能因為回收過久而導(dǎo)致系統(tǒng)長期的停頓,因此需要執(zhí)行回收策略。Redis允許配置6種回收策略胀葱,在內(nèi)存達到最大時漠秋,將會淘汰鍵值,并進行回收抵屿。內(nèi)存回收策略如下:
volatile-lru :采用LRU算法(最近最少使用算法)庆锦,但是只淘汰超時的鍵值對。
allkeys-lru :采用LRU算法轧葛,淘汰鍵值對搂抒。
volatile-random :采用隨機淘汰策略,但是只淘汰超時的鍵值對尿扯。
allkeys-random :采用隨機淘汰策略求晶,淘汰鍵值對。
volatile-ttl? :采用TTL算法(生存周期)衷笋,淘汰存活時間最短的鍵值對芳杏。
noeviction :不淘汰任何鍵值對,內(nèi)存已滿時辟宗,進行寫操作返回錯誤爵赵。
volatile和allkeys規(guī)定是對已設(shè)置過期時間的數(shù)據(jù)集淘汰數(shù)據(jù)還是從全部數(shù)據(jù)集淘汰數(shù)據(jù),后面的lru泊脐、ttl以及random是三種不同的淘汰策略空幻,再加上一種no-enviction永不回收的策略。
使用策略規(guī)則:
1)如果數(shù)據(jù)呈現(xiàn)冪律分布晨抡,也就是一部分?jǐn)?shù)據(jù)訪問頻率高氛悬,一部分?jǐn)?shù)據(jù)訪問頻率低,則使用 allkeys-lru耘柱;
2)如果數(shù)據(jù)呈現(xiàn)平等分布如捅,也就是所有的數(shù)據(jù)訪問頻率都相同,則使用allkeys-random调煎。
Redis的過期鍵刪除策略有哪幾種镜遣?
redis數(shù)據(jù)庫鍵的過期時間都保存在過期字典中,根據(jù)系統(tǒng)時間和存活時間判斷是否過期士袄。redis有三種不同的刪除策略:
定時刪除:在設(shè)置鍵的過期時間的同時悲关,創(chuàng)建一個定時器( timer ),讓定時器在鍵的過期時間來臨時娄柳,立即執(zhí)行對鍵的刪除操作寓辱。
惰性刪除:放任鍵過期不管,但是每次從鍵空間中獲取鍵時赤拒,都檢查取得的鍵是否過期秫筏,如果過期的話诱鞠,就刪除該鍵;如果沒有過期,就返回該鍵这敬。
定期刪除: 每隔一段時間航夺,程序就對數(shù)據(jù)庫進行一次檢查,刪除里面的過期鍵崔涂。至于要刪除多少過期鍵阳掐,以及要檢查多少個數(shù)據(jù)庫, 則由算法決定冷蚂。
在這三種策略中缭保,第一種和第三種為主動刪除策略, 而第二種則為被動刪除策略帝雇。
優(yōu)缺點
1)定時刪除涮俄,對內(nèi)存友好,但是對cpu很不友好
2)惰性刪除尸闸,對cpu友好彻亲,對內(nèi)存很不友好
3)定期刪除,是兩種折中吮廉,但是苞尝,如果刪除太頻繁,將退化為定時刪除宦芦,如果刪除次數(shù)太少宙址,將退化為惰性刪除。
Redis中Pipeline有什么好處调卑,為什么要用pipeline抡砂?
pipeline是redis批量提交的一種方式,也就是把多個命令操作建立一次連接發(fā)給redis去執(zhí)行恬涧,在性能方面會比循環(huán)的單次提交會好很多注益。
pipeline的好處是可以將多次IO往返的時間縮減為一次,前提是pipeline執(zhí)行的指令之間沒有因果相關(guān)性溯捆。使用redis-benchmark進行壓測的時候可以發(fā)現(xiàn)影響redis的QPS峰值的一個重要因素是pipeline批次指令的數(shù)目丑搔。
Redis是如何實現(xiàn)的同步機制?
Redis可以使用主從同步提揍,從從同步啤月。第一次同步時,主節(jié)點做一次bgsave劳跃,并同時將后續(xù)修改操作記錄到內(nèi)存buffer谎仲,待完成后將rdb文件全量同步到復(fù)制節(jié)點,復(fù)制節(jié)點接受完成后將rdb鏡像加載到內(nèi)存刨仑。加載完成后郑诺,再通知主節(jié)點將期間修改的操作記錄同步到復(fù)制節(jié)點進行重放就完成了同步過程绞呈。
什么是緩存穿透?如何避免间景?什么是緩存雪崩?何如避免艺智?
緩存穿透
一般的緩存系統(tǒng)倘要,都是按照key去緩存查詢,如果不存在對應(yīng)的value十拣,就應(yīng)該去后端系統(tǒng)查找(比如DB)封拧。一些惡意的請求會故意查詢不存在的key,請求量很大,就會對后端系統(tǒng)造成很大的壓力夭问。這就叫做緩存穿透泽西。
如何避免?
1)對查詢結(jié)果為空的情況也進行緩存缰趋,緩存時間設(shè)置短一點捧杉,或者該key對應(yīng)的數(shù)據(jù)insert了之后清理緩存。
2)對一定不存在的key進行過濾秘血∥抖叮可以把所有的可能存在的key放到一個大的Bitmap中,查詢時通過該bitmap過濾灰粮。
緩存雪崩
當(dāng)緩存服務(wù)器重啟或者大量緩存集中在某一個時間段失效仔涩,這樣在失效的時候,會給后端系統(tǒng)帶來很大壓力粘舟。導(dǎo)致系統(tǒng)崩潰熔脂。
如何避免?
1)在緩存失效后柑肴,通過加鎖或者隊列來控制讀數(shù)據(jù)庫寫緩存的線程數(shù)量霞揉。比如對某個key只允許一個線程查詢數(shù)據(jù)和寫緩存,其他線程等待嘉抒。
2)做二級緩存零聚,A1為原始緩存,A2為拷貝緩存些侍,A1失效時隶症,可以訪問A2,A1緩存失效時間設(shè)置為短期岗宣,A2設(shè)置為長期蚂会。
3)不同的key,設(shè)置不同的過期時間耗式,讓緩存失效的時間點盡量均勻胁住。
為什么Redis要把所有數(shù)據(jù)放到內(nèi)存中趁猴?
Redis為了達到最快的讀寫速度將數(shù)據(jù)都讀到內(nèi)存中,并通過異步的方式將數(shù)據(jù)寫入磁盤彪见。所以Redis具有快速和數(shù)據(jù)持久化的特性儡司。
如果不將數(shù)據(jù)放到內(nèi)存中,磁盤的I/O速度會嚴(yán)重影響redis的性能余指。在內(nèi)存越來越便宜的今天捕犬,redis將會越來越受歡迎。如果設(shè)置了最大使用的內(nèi)存酵镜,則數(shù)據(jù)已有記錄數(shù)達到內(nèi)存限值后將不能繼續(xù)插入新值碉碉。
Redis集群的原理是什么?
1)Redis Sentinal著眼于高可用淮韭,在master宕機時會自動將slave提升為master垢粮,繼續(xù)提供服務(wù)。
2)Redis Cluster著眼于擴展性靠粪,在單個redis內(nèi)存不足時蜡吧,使用Cluster進行分片存儲。
Redis集群在什么情況下會導(dǎo)致整個集群不可用占键?
假設(shè)有A斩跌,B,C三個節(jié)點的集群捞慌,在沒有復(fù)制模型的情況下耀鸦,如果節(jié)點B失敗了,那么整個集群就會以為缺少5501-11000這個范圍的槽而不可用啸澡。
Redis集群的主從復(fù)制模型是怎樣的袖订?
為了使在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用,所以集群使用了主從復(fù)制模型,每個節(jié)點都會有N-1個復(fù)制品嗅虏。
Redis key的過期時間和永久有效分別怎么設(shè)置洛姑?
Redis key的過期時間是EXPIRE命令;Redis key的永久有效是PERSIST命令皮服。
Redis支持的Java客戶端都有哪些楞艾?官方推薦用哪個?
Redisson龄广、Jedis硫眯、lettuce等等,官方推薦使用Redisson择同。
說說Redis哈希槽的概念两入?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384個哈希槽敲才,每個key通過CRC16校驗后對16384取模來決定放置哪個槽裹纳,集群的每個節(jié)點負(fù)責(zé)一部分hash槽择葡。
怎么理解Redis事務(wù)?
事務(wù)是一個單獨的隔離操作:事務(wù)中的所有命令都會序列化剃氧、按順序地執(zhí)行敏储,事務(wù)在執(zhí)行的過程中,不會被其他客戶端發(fā)送來的命令請求所打斷朋鞍。事務(wù)是一個原子操作:事務(wù)中的命令要么全部被執(zhí)行虹曙,要么全部都不執(zhí)行。
Redis集群如何復(fù)制番舆?最大節(jié)點數(shù)?是否支持選擇數(shù)據(jù)庫矾踱?
Redis集群是采用異步復(fù)制的恨狈;其最大節(jié)點數(shù)是16384個;目前無法做到選擇性數(shù)據(jù)庫呛讲,默認(rèn)從零數(shù)據(jù)庫開始禾怠。
Redis和Redisson有什么關(guān)系?
Redisson是一個高級的分布式協(xié)調(diào)Redis客服端贝搁,能幫助用戶在分布式環(huán)境中輕松實現(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)缺點?
Jedis是Redis的Java實現(xiàn)的客戶端雷逆,其API提供了比較全面的Redis命令的支持弦讽;
Redisson實現(xiàn)了分布式和可擴展的Java數(shù)據(jù)結(jié)構(gòu),和Jedis相比膀哲,功能較為簡單往产,不支持字符串操作,不支持排序某宪、事務(wù)仿村、管道、分區(qū)等 Redis 特性兴喂。Redisson的宗旨是促進使用者對Redis的關(guān)注分離蔼囊,從而讓使用者能夠?qū)⒕Ω械胤旁谔幚順I(yè)務(wù)邏輯上。
怎么理解Redis事務(wù)衣迷?相關(guān)命令有哪些畏鼓?
1)事務(wù)是一個單獨的隔離操作:事務(wù)中的所有命令都會序列化、按順序地執(zhí)行壶谒。
2)事務(wù)在執(zhí)行的過程中滴肿,不會被其他客戶端發(fā)送來的命令請求所打斷。
3)事務(wù)是一個原子操作:事務(wù)中的命令要么全部被執(zhí)行佃迄,要么全部都不執(zhí)行泼差。
Redis事務(wù)相關(guān)的命令有MULTI(開始)贵少、EXEC(結(jié)束)、DISCARD(撤銷)堆缘、WATCH(樂觀鎖)滔灶。
如果有大量的key需要設(shè)置同一時間過期,一般需要注意什么吼肥?
如果大量的key過期時間設(shè)置的過于集中录平,到過期的那個時間點,redis可能會出現(xiàn)短暫的卡頓現(xiàn)象缀皱。一般需要在時間上加一個隨機值斗这,使得過期時間分散一些。
Redis適合的場景有哪些啤斗?
1表箭、會話緩存(Session Cache)
最常用的一種使用 Redis 的情景是會話緩存(session cache)。用 Redis 緩存會話比其他存儲(如 Memcached)的優(yōu)勢在于:Redis 提供持久化钮莲。當(dāng)維護一個不是嚴(yán)格要求一致性的緩存時免钻,如果用戶的購物車信息全部丟失,大部分人都會不高興的崔拥,現(xiàn)在极舔,他們還會這樣嗎?幸運的是链瓦,隨著 Redis 這些年的改進拆魏,很容易找到怎么恰當(dāng)?shù)氖褂?Redis 來緩存會話的文檔。甚至廣為人知的商業(yè)平臺Magento 也提供 Redis 的插件慈俯。
2稽揭、全頁緩存(FPC)
除基本的會話 token 之外,Redis 還提供很簡便的 FPC 平臺肥卡∠疲回到一致性問題,即使重啟了 Redis 實例步鉴,因為有磁盤的持久化揪胃,用戶也不會看到頁面加載速度的下降,這是一個極大改進氛琢,類似 PHP 本地 FPC喊递。再次以 Magento 為例,Magento提供一個插件來使用 Redis 作為全頁緩存后端阳似。此外骚勘,對 WordPress 的用戶來說,Pantheon 有一個非常好的插件 wp-redis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面俏讹。
3当宴、隊列
Reids 在內(nèi)存存儲引擎領(lǐng)域的一大優(yōu)點是提供 list 和 set 操作,這使得 Redis能作為一個很好的消息隊列平臺來使用泽疆。Redis 作為隊列使用的操作户矢,就類似于本地程序語言(如 Python)對 list 的 push/pop 操作。如果你快速的在 Google中搜索“Redis queues”殉疼,你馬上就能找到大量的開源項目梯浪,這些項目的目的就是利用 Redis 創(chuàng)建非常好的后端工具,以滿足各種隊列需求瓢娜。例如挂洛,Celery 有一個后臺就是使用 Redis 作為 broker,你可以從這里去查看眠砾。
4虏劲、排行榜/計數(shù)器
Redis 在內(nèi)存中對數(shù)字進行遞增或遞減的操作實現(xiàn)的非常好。集合(Set)和有序集合(Sorted Set)也使得我們在執(zhí)行這些操作的時候變的非常簡單荠藤,Redis 只是正好提供了這兩種數(shù)據(jù)結(jié)構(gòu)。所以获高,我們要從排序集合中獲取到排名最靠前的 10個用戶–我們稱之為“user_scores”哈肖,我們只需要像下面一樣執(zhí)行即可:當(dāng)然,這是假定你是根據(jù)你用戶的分?jǐn)?shù)做遞增的排序念秧。如果你想返回用戶及用戶的分?jǐn)?shù)淤井,你需要這樣執(zhí)行:ZRANGE user_scores 0 10 WITHSCORES Agora Games 就是一個很好的例子,用 Ruby 實現(xiàn)的摊趾,它的排行榜就是使用 Redis 來存儲數(shù)據(jù)的币狠,你可以在這里看到。
5砾层、發(fā)布/訂閱
最后(但肯定不是最不重要的)是 Redis 的發(fā)布/訂閱功能漩绵。發(fā)布/訂閱的使用場景確實非常多。我已看見人們在社交網(wǎng)絡(luò)連接中使用肛炮,還可作為基于發(fā)布/訂閱的腳本觸發(fā)器止吐,甚至用 Redis 的發(fā)布/訂閱功能來建立聊天系統(tǒng)。
一個Redis實例最多能存放多少的keys侨糟?List碍扔、Set、Sorted Set他們最多能存放多少元素秕重?
理論上Redis可以處理多達232的keys不同,并且在實際中進行了測試,每個實例至少存放了2億5千萬的keys。任何list二拐、set和sorted set都可以存放232個元素服鹅。換句話說,Redis的存儲極限是系統(tǒng)中的可用內(nèi)存值卓鹿。
Redis持久化數(shù)據(jù)和緩存怎么做擴容菱魔?
如果Redis被當(dāng)做緩存使用,使用一致性哈希實現(xiàn)動態(tài)擴容縮容吟孙。如果Redis被當(dāng)做一個持久化存儲使用澜倦,必須使用固定的keys-to-nodes映射關(guān)系,節(jié)點的數(shù)量一旦確定不能變化杰妓,否則(即Redis節(jié)點需要動態(tài)變化的情況)必須使用可以在運行時進行數(shù)據(jù)再平衡的一套系統(tǒng)藻治,而當(dāng)前只有Redis集群可以做到這樣。
Redis如何做內(nèi)存優(yōu)化巷挥?
盡可能使用散列表(hashes)桩卵,散列表(是說散列表里面存儲的數(shù)少)使用的內(nèi)存非常小,所以應(yīng)該盡可能的將數(shù)據(jù)模型抽象到一個散列表里面倍宾。如web系統(tǒng)中有一個用戶對象雏节,不要為這個用戶的名稱,姓氏高职,郵箱钩乍,密碼設(shè)置單獨的key,而是應(yīng)該把這個用戶的所有信息存儲到一張散列表里面怔锌。
Redis回收進程如何工作的寥粹?
Redis內(nèi)存回收機制主要體現(xiàn)在以下兩個方面:
1)刪除到達時間的鍵對象。
2)內(nèi)存使用達到maxmemory上限時觸發(fā)內(nèi)存溢出控制策略埃元。
1涝涤、刪除過期鍵對象
Redis所有的鍵都可以設(shè)置過期屬性,內(nèi)部保存在過期字典中岛杀。由于進程內(nèi)保存了大量的鍵阔拳,維護每個鍵精準(zhǔn)的過期刪除機制會導(dǎo)致消耗大量的CPU,對于單線程的Redis來說成本過高类嗤,因此Redis采用惰性刪除和定時任務(wù)刪除機制實現(xiàn)過期鍵的內(nèi)存回收衫生。
惰性刪除:惰性刪除用于當(dāng)客戶端讀取帶有超時屬性的鍵時,如果已經(jīng)超過鍵設(shè)置的過期時間土浸,會執(zhí)行刪除操作并返回空罪针,這種策略是出于節(jié)省CPU成本考慮,不需要單獨維護TTL鏈表來處理過期鍵的刪除黄伊。但是單獨用這種方式存在內(nèi)存泄露的問題泪酱,當(dāng)過期鍵一直沒有訪問將無法得到及時刪除,從而導(dǎo)致內(nèi)存不能及時釋放。正因為如此墓阀,Redis還提供另一種定時任務(wù)刪除機制作為惰性刪除的補充毡惜。
定時任務(wù)刪除:Redis內(nèi)部維護一個定時任務(wù),默認(rèn)每秒運行10次(通過配置hz控制)斯撮。定時任務(wù)中刪除過期鍵邏輯采用了自適應(yīng)算法经伙,根據(jù)鍵的過期比例,使用快慢兩種速率模式回收鍵勿锅。
比如:
定時任務(wù)在每個數(shù)據(jù)庫空間隨機檢查20個鍵帕膜,當(dāng)發(fā)現(xiàn)過期時刪除對應(yīng)的鍵。
如果超過檢查數(shù)25%的鍵過期溢十,循環(huán)執(zhí)行回收邏輯直到不足25%或運行超時為止垮刹,慢模式下超時時間為25ms。
如果之前回收鍵邏輯超時张弛,則在Redis觸發(fā)內(nèi)部事件之前再次以快模式運行回收過期鍵任務(wù)荒典,快模式下超時時間為1ms且2s內(nèi)只能運行1次。
快慢兩種模式內(nèi)部刪除邏輯相同吞鸭,只是執(zhí)行的超時時間不同寺董。
2、內(nèi)存溢出控制策略
當(dāng)Redis所用內(nèi)存達到maxmemory上限時會觸發(fā)相應(yīng)的溢出控制策略刻剥。具體策略受maxmemory-policy參數(shù)控制遮咖,Redis支持6種策略,如下所示:
noeviction:默認(rèn)策略透敌,當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時盯滚,新寫入操作會報錯踢械。應(yīng)該沒人用吧酗电。
allkeys-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時,在鍵空間中内列,移除最近最少使用的 Key撵术。推薦使用,目前項目在用這種话瞧。
allkeys-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時嫩与,在鍵空間中,隨機移除某個 Key交排。應(yīng)該也沒人用吧划滋,你不刪最少使用 Key,去隨機刪埃篓。
volatile-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時处坪,在設(shè)置了過期時間的鍵空間中,移除最近最少使用的 Key。這種情況一般是把 Redis 既當(dāng)緩存同窘,又做持久化存儲的時候才用玄帕。不推薦。
volatile-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時想邦,在設(shè)置了過期時間的鍵空間中裤纹,隨機移除某個 Key。依然不推薦丧没。
volatile-ttl:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時鹰椒,在設(shè)置了過期時間的鍵空間中,有更早過期時間的 Key 優(yōu)先移除骂铁。不推薦吹零。如果沒有對應(yīng)的鍵,則回退到noeviction策略拉庵。