Redis是?單進程單線程?的罕邀,Redis利用隊列技術(shù)將并發(fā)訪問變?yōu)榇性L問畅形,消除了傳統(tǒng)數(shù)據(jù)庫串行控制的開銷。
Redis為什么是單線程的诉探?
多線程處理會涉及到鎖日熬,而且多線程處理會設(shè)計到線程切換而消耗CPU。因為CPU不會Redis的瓶頸肾胯,Redis的瓶頸最有可能是機器內(nèi)存或者網(wǎng)絡(luò)帶寬竖席。單線程無法發(fā)揮多核CPU性能,不過可以通過在單機開啟Redis實例來解決敬肚。
Redis的優(yōu)勢
**速度快毕荐。**因為數(shù)據(jù)存儲于內(nèi)存中,類似于HashMap艳馒,HashMap的優(yōu)勢就是查找和操作的時間復(fù)雜度都是O(1)
支持豐富的數(shù)據(jù)類型?憎亚,支持string员寇,list,set第美,sorted set蝶锋,hash
支持事務(wù)?,操作都是原子性什往,所謂的原子性就是對數(shù)據(jù)的更改要么全部執(zhí)行扳缕,要么全部不執(zhí)行
豐富的特性?:可用于緩存,消息别威,按key設(shè)置過期時間躯舔,過期后將會自動刪除
Redis和memcached有哪些優(yōu)勢
memcached所有的值均是簡單的字符串,Reids作為其替代者省古,支持更為豐富的數(shù)據(jù)類型
Redis的速度比memcached快很多
Redis可以持久化其數(shù)據(jù)
Redis支持數(shù)據(jù)的備份粥庄,即master/slave模式的數(shù)據(jù)備份
Redis key的過期時間和永久有效分別怎么設(shè)置?
EXPIRE 和 PERSIST 命令豺妓。
Redis 主要消耗什么物理資源飒赃?
內(nèi)存。
為什么Redis需要把所有數(shù)據(jù)放到內(nèi)存中科侈?
Redis為了達到最快的讀寫速度將數(shù)據(jù)都讀到內(nèi)存中,并通過異步的方式將數(shù)據(jù)寫入磁盤炒事。
所以redis具有快速和數(shù)據(jù)持久化的特征臀栈。如果不將數(shù)據(jù)放在內(nèi)存中,磁盤I/O速度為嚴重影響redis的性能挠乳。
在內(nèi)存越來越便宜的今天权薯,redis將會越來越受歡迎。 如果設(shè)置了最大使用的內(nèi)存睡扬,則數(shù)據(jù)已有記錄數(shù)達到內(nèi)存限值后不能繼續(xù)插入新值盟蚣。
說說Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念卖怜,Redis集群有16384個哈希槽屎开,每個key通過CRC16校驗后對16384取模來決定放置哪個槽,集群的每個節(jié)點負責一部分hash槽马靠。
Redis中的管道有什么用奄抽?
一次請求/響應(yīng)服務(wù)器能實現(xiàn)處理新的請求即使舊的請求還未被響應(yīng)。這樣就可以將多個命令發(fā)送到服務(wù)器甩鳄,而不用等待回復(fù)逞度,最后在一個步驟中讀取該答復(fù)。
這就是管道(pipelining)妙啃,是一種幾十年來廣泛使用的技術(shù)档泽。例如許多POP3協(xié)議已經(jīng)實現(xiàn)支持這個功能,大大加快了從服務(wù)器下載新郵件的過程。
怎么理解Redis事務(wù)馆匿?
事務(wù)是一個單獨的隔離操作:事務(wù)中的所有命令都會序列化抑胎、按順序地執(zhí)行。事務(wù)在執(zhí)行的過程中甜熔,不會被其他客戶端發(fā)送來的命令請求所打斷圆恤。
事務(wù)是一個原子操作:事務(wù)中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行腔稀。
Redis 事務(wù)相關(guān)的命令有哪幾個盆昙?
MULTI 、 EXEC 焊虏、 DISCARD 淡喜、 WATCH
Redis內(nèi)存回收機制
Redis的內(nèi)存回收主要圍繞以下兩個方面:
Redis過期策略?:刪除過期時間的key值
Redis淘汰策略?:內(nèi)存使用到達maxmemory上限時觸發(fā)內(nèi)存淘汰數(shù)據(jù)
Redis過期策略
Redis過期策略通常有以下三種:
定時過期每個設(shè)置過期時間的key都需要創(chuàng)建一個定時器,到過期時間就會立即清除诵闭。該策略可以立即清除過期的數(shù)據(jù)炼团,對內(nèi)存很友好;但是會占用大量的CPU資源去處理過期的數(shù)據(jù)疏尿,從而影響緩存的響應(yīng)時間和吞吐量瘟芝。
惰性過期只有當訪問一個key時,才會判斷該key是否已過期褥琐,過期則清除锌俱。該策略可以最大化地節(jié)省CPU資源,卻對內(nèi)存非常不友好敌呈。極端情況可能出現(xiàn)大量的過期key沒有再次被訪問贸宏,從而不會被清除,占用大量內(nèi)存磕洪。
定期過期每隔一定的時間吭练,會掃描一定數(shù)量的數(shù)據(jù)庫的expires字典中一定數(shù)量的key,并清除其中已過期的key析显。該策略是前兩者的一個折中方案鲫咽。通過調(diào)整定時掃描的時間間隔和每次掃描的限定耗時,可以在不同情況下使得CPU和內(nèi)存資源達到最優(yōu)的平衡效果谷异。
Redis中同時使用了?惰性過期?和?定期過期?兩種過期策略浑侥。
Redis有哪幾種數(shù)據(jù)淘汰策略
在Redis中,允許用戶設(shè)置最大使用內(nèi)存大小 server.maxmemory 晰绎,當Redis內(nèi)存數(shù)據(jù)集大小上升到一定大小的時候寓落,就會執(zhí)行數(shù)據(jù)淘汰策略
volatile-lru?:從已設(shè)置過期的數(shù)據(jù)集中挑選最近最少使用的淘汰
volatile-ttl?:從已設(shè)置過期的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰
volatile-random?:從已設(shè)置過期的數(shù)據(jù)集中任意挑選數(shù)據(jù)淘汰
allkeys-lru?:從數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰
allkeys-random?:從數(shù)據(jù)集中任意挑選數(shù)據(jù)淘汰
noenviction?:禁止淘汰數(shù)據(jù)
Redis支持哪幾種持久化方式
RDB持久化原理是將Redis在內(nèi)存中的數(shù)據(jù)記錄定時dump到磁盤上的RDB文件。 指定的時間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤荞下,實際操作過程是fork一個子進程伶选,先將數(shù)據(jù)集寫入臨時文件史飞,寫入成功后,再替換之前的文件仰税,用二進制壓縮存儲构资。
AOF(append only file)持久化原理是將Redis的操作日志以追加的方式寫入文件。 以日志的形式記錄服務(wù)器所處理的每一個寫陨簇、刪除操作吐绵,查詢操作不會記錄,以文本的方式記錄河绽,可以打開文件看到詳細的操作記錄己单。當服務(wù)器重啟的時候會重新執(zhí)行這些命令來恢復(fù)原始的數(shù)據(jù)。AOF命令以Reids協(xié)議追加保存每次寫的操作到文件末尾耙饰。Redis還能對AOF文件進行后臺重寫纹笼,使得AOF文件的體積不至于過大。
Redis兩種持久化方式優(yōu)缺點苟跪?
RDB持久化
優(yōu)點:RDB文件緊湊廷痘,體積小,網(wǎng)絡(luò)傳輸快件已,適合全量復(fù)制笋额;恢復(fù)速度比AOF快很多。當然篷扩,與AOF相比鳞陨,RDB最重要的優(yōu)點之一是對性能的影響相對較小
缺點:RDB文件的致命缺點在與其數(shù)據(jù)快照的持久化方式?jīng)Q定了必然做不到實時持久化,而在數(shù)據(jù)越來越重要的今天瞻惋,數(shù)據(jù)的大量丟失很多時候是無法接受的,因此AOF持久化稱為主流援岩。此外歼狼,RDB文件需要滿足特定格式,兼容性差享怀。
AOF持久化與RDB持久化相對應(yīng),AOF的優(yōu)點在于支持秒級持久化羽峰、兼容性好,缺點是文件大添瓷,恢復(fù)速度慢梅屉,對性能影響大
如何選擇Redis持久化方式策略?
在介紹持久化策略之前鳞贷,首先要明白無論是RDB還是AOF坯汤,持久化的開啟都是要付出性能方面的代價的。對比RDB持久化搀愧,一方面是bdsave在進行fork操作時Redis主進程會阻塞惰聂,另一方面疆偿,子進程向硬盤寫數(shù)據(jù)也會帶來IO壓力;對于AOF持久化搓幌,向硬盤寫數(shù)據(jù)的頻率大大提高(everysec策略下為秒級)杆故,IO壓力更大,設(shè)置可能造成AOF追加阻塞文件溉愁。此外处铛,AOF文件的重寫與RDB的basave類似,會有fork時的阻塞和子進程的IO壓力問題拐揭。相對來說撤蟆,由于AOF向硬盤中寫數(shù)據(jù)的頻率更高,因此對Redis主進程性能的影響會更大投队。
在實際生產(chǎn)環(huán)境中枫疆,根據(jù)數(shù)據(jù)量、應(yīng)用對數(shù)據(jù)的安全要求敷鸦、預(yù)算限制等不同情況息楔,會有各種各樣的持久化策略;如完全不使用任何持久化扒披,使用RDB或AOF一種值依,或同事開啟RDB和AOF持久化等。此外碟案,持久化的選擇必須與Redis的主從策略一起考慮愿险,因為主從復(fù)制與持久化同樣具有數(shù)據(jù)備份的功能,而且主機master和從機slave可以獨立的選擇持久化方案价说。
為什么要做Redis分區(qū)辆亏?
分區(qū)可以讓Redis管理更大的內(nèi)存,Redis將可以使用所有機器的內(nèi)存鳖目。如果沒有分區(qū)扮叨,你最多只能使用一臺機器的內(nèi)存。分區(qū)使Redis的計算能力通過簡單地增加計算機得到成倍提升,Redis的網(wǎng)絡(luò)帶寬也會隨著計算機和網(wǎng)卡的增加而成倍增長领迈。
Redis集群的主從復(fù)制模型是怎樣的彻磁?
為了是在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用,所以集群是用了主從復(fù)制模型狸捅,每個節(jié)點都會有N-1個復(fù)制品
Redis集群會有寫操作丟失嗎衷蜓?為什么?
Redis并不能保證數(shù)據(jù)強一致性尘喝,這意味著在實際中集群在特定的條件下可能會丟失寫操作
Redis集群之間是如何復(fù)制的
異步復(fù)制磁浇。
Redis如何做內(nèi)存優(yōu)化
盡可能使用散列表(hashes),散列表(是說列表里面存儲的數(shù)少)使用的內(nèi)存非常小朽褪,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個散列表里面扯夭,比如你的web系統(tǒng)中有一個用戶對象鳍贾,不要為這個用戶的名稱,姓氏交洗,郵箱骑科,密碼設(shè)置單獨的key,而是應(yīng)該把這個用戶所有信息存儲到一張散列表中构拳。
Redis常用的使用場景
Session共享(單點登錄)
頁面緩存
隊列
排行榜/計算器
發(fā)布/訂閱
Redis有哪些架構(gòu)模式咆爽?講講各自的特點?
單機版
特點:簡單
存在問題:
內(nèi)存容量有限
處理能力有限
無法高可用
主從復(fù)制
Redis的復(fù)制(replication)功能允許用戶根據(jù)一個Redis服務(wù)器來創(chuàng)建任意多個該服務(wù)器的復(fù)制品置森,其中被復(fù)制的服務(wù)器為主服務(wù)器(master)斗埂,而通過復(fù)制創(chuàng)建出來的服務(wù)器復(fù)制品則為從服務(wù)器(slave)。主要主從服務(wù)器之間的網(wǎng)絡(luò)連接正常凫海,主從服務(wù)器兩者會具有相同的數(shù)據(jù)呛凶,主服務(wù)器就會一直將發(fā)生在自己身上的數(shù)據(jù)更新同步給從服務(wù)器,從而一直保證主從服務(wù)器的數(shù)據(jù)相同行贪。
問題:
無法保證高可用
沒有解決master寫的壓力
哨兵
Redis sentinel 是一個分布式系統(tǒng)中監(jiān)控 redis 主從服務(wù)器漾稀,并在主服務(wù)器下線時自動進行故障轉(zhuǎn)移。其中三個特性:
監(jiān)控(Monitoring): Sentinel 會不斷地檢查你的主服務(wù)器和從服務(wù)器是否運作正常建瘫。
提醒(Notification): 當被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時崭捍, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
自動故障遷移(Automatic failover): 當一個主服務(wù)器不能正常工作時啰脚, Sentinel 會開始一次自動故障遷移操作殷蛇。
特點:
保證高可用
監(jiān)控各個節(jié)點
自動故障遷移
缺點:
主從模式,切換需要時間橄浓,會丟數(shù)據(jù)
沒有解決master寫的壓力
集群(proxy型)
Twemproxy 是一個 Twitter 開源的一個 redis 和 memcache 快速/輕量級代理服務(wù)器粒梦; Twemproxy 是一個快速的單線程代理程序,支持 Memcached ASCII 協(xié)議和 redis 協(xié)議荸实。
特點:
多種 hash 算法:MD5匀们、CRC16、CRC32泪勒、CRC32a、hsieh宴猾、murmur圆存、Jenkins
支持失敗節(jié)點自動刪除
后端 Sharding 分片邏輯對業(yè)務(wù)透明,業(yè)務(wù)方的讀寫方式和操作單個 Redis 一致
缺點:
增加了新的 proxy仇哆,需要維護其高可用沦辙。
failover 邏輯需要自己實現(xiàn),其本身不能支持故障的自動轉(zhuǎn)移可擴展性差讹剔,進行擴縮容都需要手動干預(yù)
集群(直連型)
從redis 3.0之后版本支持redis-cluster集群油讯,Redis-Cluster采用無中心結(jié)構(gòu)详民,每個節(jié)點保存數(shù)據(jù)和整個集群狀態(tài),每個節(jié)點都和其他所有節(jié)點連接。
特點:
無中心架構(gòu)(不存在哪個節(jié)點影響性能瓶頸)陌兑,少了 proxy 層沈跨。
數(shù)據(jù)按照 slot 存儲分布在多個節(jié)點,節(jié)點間數(shù)據(jù)共享兔综,可動態(tài)調(diào)整數(shù)據(jù)分布饿凛。
可擴展性,可線性擴展到 1000 個節(jié)點软驰,節(jié)點可動態(tài)添加或刪除涧窒。
高可用性,部分節(jié)點不可用時锭亏,集群仍可用纠吴。通過增加 Slave 做備份數(shù)據(jù)副本
實現(xiàn)故障自動 failover,節(jié)點之間通過 gossip 協(xié)議交換狀態(tài)信息慧瘤,用投票機制完成 Slave到 Master的角色提升戴已。
缺點:
資源隔離性較差,容易出現(xiàn)相互影響的情況碑隆。
數(shù)據(jù)通過異步復(fù)制,不保證數(shù)據(jù)的強一致性
使用過Redis分布式鎖嗎恭陡,它是怎么實現(xiàn)的?
先拿setnx來爭搶鎖上煤,搶到之后休玩,再用expire給鎖加一個過期時間防止鎖忘記了釋放。 如果在setnx之后執(zhí)行expire之前進程意外crash或者要重啟維護了劫狠,那會怎么樣拴疤? set指令有非常復(fù)雜的參數(shù),這個應(yīng)該是可以同時把setnx和expire合成一條指令來用的独泞!
使用過 Redis 做異步隊列么呐矾,你是怎么用的?有什么缺點懦砂?
般使用 list 結(jié)構(gòu)作為隊列蜒犯,rpush 生產(chǎn)消息,lpop 消費消息荞膘。當 lpop 沒有消息的時候罚随,要適當 sleep一會再重試。
缺點:
在消費者下線的情況下羽资,生產(chǎn)的消息會丟失缴罗,得使用專業(yè)的消息隊列如 rabbitmq 等蝶柿。
能不能生產(chǎn)一次消費多次呢工禾?
使用 pub/sub 主題訂閱者模式欣簇,可以實現(xiàn) 1:N 的消息隊列。
什么是緩存穿透?如何避免?
緩存穿透
一般的緩存系統(tǒng),都是按照key去緩存查詢翰萨,如果不存在對應(yīng)的value,就應(yīng)該去后端系統(tǒng)查找(比如DB)趾疚。一些惡意的請求會故意查詢不存在的key,請求量很大缨历,就會對后端系統(tǒng)造成很大的壓力。這就叫做緩存穿透糙麦。
如何避免辛孵?
對查詢結(jié)果為空的情況也進行緩存,緩存時間設(shè)置短一點赡磅,或者該key對應(yīng)的數(shù)據(jù)insert了之后清理緩存魄缚。
對一定不存在的key進行過濾》倮龋可以把所有的可能存在的key放到一個大的Bitmap中冶匹,查詢時通過該bitmap過濾。
什么是緩存雪崩咆瘟?何如避免嚼隘?
緩存雪崩當緩存服務(wù)器重啟或者大量緩存集中在某一個時間段失效,這樣在失效的時候袒餐,會給后端系統(tǒng)帶來很大壓力飞蛹,導(dǎo)致系統(tǒng)崩潰。
如何避免灸眼?
在緩存失效后卧檐,通過加鎖或者隊列來控制讀數(shù)據(jù)庫寫緩存的線程數(shù)量。比如對某個key只允許一個線程查詢數(shù)據(jù)和寫緩存焰宣,其他線程等待霉囚。
做二級緩存,A1為原始緩存匕积,A2為拷貝緩存盈罐,A1失效時,可以訪問A2闪唆,A1緩存失效時間設(shè)置為短期盅粪,A2設(shè)置為長期 3:不同的key,設(shè)置不同的過期時間苞氮,讓緩存失效的時間點盡量均勻
緩存并發(fā)
這里的并發(fā)指的是多個redis的client同時set key引起的并發(fā)問題湾揽。其實redis自身就是單線程操作瓤逼,多個client并發(fā)操作笼吟,按照先到先執(zhí)行的原則库物,先到的先執(zhí)行,其余的阻塞贷帮。當然戚揭,另外的解決方案是把redis.set操作放在隊列中使其串行化,必須的一個一個執(zhí)行撵枢。
緩存預(yù)熱
緩存預(yù)熱就是系統(tǒng)上線后民晒,將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。
這樣就可以避免在用戶請求的時候锄禽,先查詢數(shù)據(jù)庫潜必,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)沃但!
解決思路:
直接寫個緩存刷新頁面磁滚,上線時手工操作下;
數(shù)據(jù)量不大宵晚,可以在項目啟動的時候自動進行加載垂攘;
目的就是在系統(tǒng)上線前,將數(shù)據(jù)加載到緩存中淤刃。
Redis回收進程如何工作的晒他?
客戶端執(zhí)行數(shù)據(jù)寫入操作
redis server接收到寫入操作之后,檢查maxmemory的限制逸贾,如果超過了限制陨仅,那么就根據(jù)對應(yīng)的policy清理掉部分數(shù)據(jù)
寫入操作完成執(zhí)行。
Redis是單線程的耕陷,如何提高多核CPU的利用率掂名?
可以在同一個服務(wù)器部署多個Redis的實例,并把他們當作不同的服務(wù)器來使用哟沫,在某些時候饺蔑,無論如何一個服務(wù)器是不夠的, 所以嗜诀,如果你想使用多個CPU猾警,你可以考慮一下分片(shard)。
修改配置不重啟Redis會實時生效嗎隆敢?
針對運行實例发皿,有許多配置選項可以通過 CONFIG SET 命令進行修改,而無需執(zhí)行任何形式的重啟拂蝎。 從 Redis 2.2 開始穴墅,可以從 AOF 切換到 RDB 的快照持久性或其他方式而不需要重啟 Redis。檢索 CONFIG GET * 命令獲取更多信息。 但偶爾重新啟動是必須的玄货,如為升級 Redis 程序到新的版本皇钞,或者當你需要修改某些目前 CONFIG 命令還不支持的配置參數(shù)的時候。
Redis的內(nèi)存用完了會發(fā)生什么松捉?
如果達到設(shè)置的上限夹界,Redis的寫命令會返回錯誤信息(但是讀命令還可以正常返回。)或者你可以將Redis當緩存來使用配置淘汰機制隘世,當Redis達到內(nèi)存上限時會沖刷掉舊的內(nèi)容可柿。
分布式Redis是前期做還是后期規(guī)模上來了再做好?為什么丙者?
既然Redis是如此的輕量(單實例只使用1M內(nèi)存),為防止以后的擴容复斥,最好的辦法就是一開始就啟動較多實例。即便你只有一臺服務(wù)器械媒,你也可以一開始就讓Redis以分布式的方式運行永票,使用分區(qū),在同一臺服務(wù)器上啟動多個實例滥沫。一開始就多設(shè)置幾個Redis實例侣集,例如32或者64個實例,對大多數(shù)用戶來說這操作起來可能比較麻煩兰绣,但是從長久來看做這點犧牲是值得的世分。這樣的話,當你的數(shù)據(jù)不斷增長缀辩,需要更多的Redis服務(wù)器時臭埋,你需要做的就是僅僅將Redis實例從一臺服務(wù)遷移到另外一臺服務(wù)器而已(而不用考慮重新分區(qū)的問題)。一旦你添加了另一臺服務(wù)器臀玄,你需要將你一半的Redis實例從第一臺機器遷移到第二臺機器瓢阴。
Redis與其他key-value存儲有什么不同?
Redis有著更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)并且提供對他們的原子性操作健无,這是一個不同于其他數(shù)據(jù)庫的進化路徑荣恐。Redis的數(shù)據(jù)類型都是基于基本數(shù)據(jù)結(jié)構(gòu)的同時對程序員透明,無需進行額外的抽象累贤。Redis運行在內(nèi)存中但是可以持久化到磁盤叠穆,所以在對不同數(shù)據(jù)集進行高速讀寫時需要權(quán)衡內(nèi)存,應(yīng)為數(shù)據(jù)量不能大于硬件內(nèi)存臼膏。在內(nèi)存數(shù)據(jù)庫方面的另一個優(yōu)點是硼被, 相比在磁盤上相同的復(fù)雜的數(shù)據(jù)結(jié)構(gòu),在內(nèi)存中操作起來非常簡單渗磅,這樣Redis可以做很多內(nèi)部復(fù)雜性很強的事情嚷硫。 同時检访,在磁盤格式方面他們是緊湊的以追加的方式產(chǎn)生的,因為他們并不需要進行隨機訪問仔掸。
關(guān)注獲得更多分享