Redis面試好題整理

點擊上方「藍(lán)字」關(guān)注我們

50、Redis支持哪幾種數(shù)據(jù)類型?
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet; 如果你是Redis中高級用戶,還需要加上下面幾種數(shù)據(jù)結(jié)構(gòu)HyperLogLog、Geo、Pub/Sub。
String字符串:
格式: set key value
string類型是二進(jìn)制安全的。意思是redis的string可以包含任何數(shù)據(jù)。比如jpg圖片或者序列化的對象 。
string類型是Redis最基本的數(shù)據(jù)類型,一個鍵最大能存儲512MB。
Hash(哈希)
格式: hmset name ?key1 value1 key2 value2
Redis hash 是一個鍵值(key=>value)對集合。
Redis hash是一個string類型的field和value的映射表,hash特別適合用于存儲對象。
List(列表)
Redis 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)
格式: lpush ?name ?value
在 key 對應(yīng) list 的頭部添加字符串元素
格式: rpush ?name ?value
在 key 對應(yīng) list 的尾部添加字符串元素
格式: lrem name ?index
key 對應(yīng) list 中刪除 count 個和 value 相同的元素
格式: llen name
返回 key 對應(yīng) list 的長度
Set(集合)
格式: sadd ?name ?value
Redis的Set是string類型的無序集合。
集合是通過哈希表實現(xiàn)的,所以添加,刪除,查找的復(fù)雜度都是O(1)。
zset(sorted set:有序集合)
格式: zadd ?name score value
Redis zset 和 set 一樣也是string類型元素的集合,且不允許重復(fù)的成員。
不同的是每個元素都會關(guān)聯(lián)一個double類型的分?jǐn)?shù)。redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。
zset的成員是唯一的,但分?jǐn)?shù)(score)卻可以重復(fù)。
51、什么是緩存穿透
一般的緩存系統(tǒng),都是按照key去緩存查詢,如果不存在對應(yīng)的value,就應(yīng)該去數(shù)據(jù)庫查詢。一些惡意的請求會故意大量查詢不存在的key,就會對數(shù)據(jù)庫造成很大的壓力。這就叫做緩存穿透。簡單的說就是故意避開緩存去數(shù)據(jù)庫查詢數(shù)據(jù)。。場景:當(dāng)客戶端發(fā)起查詢時,緩存中沒有就會去查庫,庫里也沒有,就會返回給客戶端錯誤信息。這樣是沒問題的,看起來邏輯是完美的,但是這里存在一個漏洞,那就是無論什么樣的Key過來查,都接受它的請求,這就可能會被黑客抓住,發(fā)起大量請求,并且Key都是系統(tǒng)中沒有的,庫里也查不到對應(yīng)的值,這樣的Key稱之為非法Key。那么當(dāng)大量這樣的請求過來時是不是都不會命中Redis,然后都會打到DB上,當(dāng)DB瞬時接收到如此多的連接時,DB就有可能撐不住,掛掉。這就是存在的一個隱藏的漏洞,黑客或者惡意攻擊者就會抓住這一點攻擊你的系統(tǒng),使你的系統(tǒng)癱瘓。
采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的bitmap中,一個一定不存在的數(shù)據(jù)會被 這個bitmap攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力。
另外也有一個更為簡單粗暴的方法(我們采用的就是這種),如果一個查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個空結(jié)果進(jìn)行緩存,但它的過期時間會很短,最長不超過五分鐘。
52、什么是緩存擊穿
是針對緩存中沒有但數(shù)據(jù)庫有的數(shù)據(jù)。場景是,當(dāng)Key失效后,假如瞬間突然涌入大量的請求,來請求同一個Key,這些請求不會命中Redis,都會請求到DB,導(dǎo)致數(shù)據(jù)庫壓力過大,甚至扛不住,掛掉。解決辦法:
設(shè)置熱點Key,自動檢測熱點Key,將熱點Key的過期時間加大或者設(shè)置為永不過期,或者設(shè)置為邏輯上永不過期,具體設(shè)置方法待會說。
加互斥鎖。當(dāng)發(fā)現(xiàn)沒有命中Redis,去查數(shù)據(jù)庫的時候,在執(zhí)行更新緩存的操作上加鎖,誰拿到鎖誰去更新,同時在拿到鎖之后先從緩存再獲取一次如果有就返回,沒有就查庫然后更新。(雙重校驗)
53、什么是緩存雪崩
緩存雪崩是指緩存中數(shù)據(jù)大批量到過期時間,而查詢數(shù)據(jù)量巨大,引起數(shù)據(jù)庫壓力過大甚至down機(jī)。和緩存擊穿不同的是, 緩存擊穿指并發(fā)查同一條數(shù)據(jù),緩存雪崩是不同數(shù)據(jù)都過期了,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫。簡單地說就是緩存大量過期去數(shù)據(jù)庫查詢數(shù)據(jù)。
解決辦法:
緩存數(shù)據(jù)的過期時間設(shè)置隨機(jī),防止同一時間大量數(shù)據(jù)過期現(xiàn)象發(fā)生。
如果緩存數(shù)據(jù)庫是分布式部署,將熱點數(shù)據(jù)均勻分布在不同搞得緩存數(shù)據(jù)庫中。
設(shè)置熱點數(shù)據(jù)永遠(yuǎn)不過期。
54、Redis有哪些架構(gòu)模式?各有什么特點
單機(jī)版
特點:
簡單
問題:
1、內(nèi)存容量有限
2、處理能力有限
3、無法高可用。
主從復(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ù)相同。
特點:
1、master/slave 角色
2、master/slave 數(shù)據(jù)相同
3、降低 master 讀壓力在轉(zhuǎn)交從庫
問題:
無法保證高可用
沒有解決 master 寫的壓力
哨兵
Redis sentinel 是一個分布式系統(tǒng)中監(jiān)控 redis 主從服務(wù)器,并在主服務(wù)器下線時自動進(jìn)行故障轉(zhuǎn)移。其中三個特性:
監(jiān)控(Monitoring):? ?Sentinel ?會不斷地檢查你的主服務(wù)器和從服務(wù)器是否運(yùn)作正常。
提醒(Notification):當(dāng)被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
自動故障遷移(Automatic failover):當(dāng)一個主服務(wù)器不能正常工作時, Sentinel 會開始一次自動故障遷移操作。
特點:
1、保證高可用
2、監(jiān)控各個節(jié)點
3、自動故障遷移
缺點:主從模式,切換需要時間丟數(shù)據(jù)
沒有解決 master寫的壓力
集群(proxy 型)
Twemproxy 是一個 Twitter 開源的一個 redis 和 memcache 快速/輕量級代理服務(wù)器;Twemproxy 是一個快速的單線程代理程序,支持 Memcached ASCII 協(xié)議和 redis 協(xié)議。
特點:
1、多種 hash 算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins
2、支持失敗節(jié)點自動刪除
3、后端 Sharding 分片邏輯對業(yè)務(wù)透明,業(yè)務(wù)方的讀寫方式和操作單個 Redis 一致
缺點:
增加了新的 proxy,需要維護(hù)其高可用。
failover 邏輯需要自己實現(xiàn),其本身不能支持故障的自動轉(zhuǎn)移可擴(kuò)展性差,進(jìn)行擴(kuò)縮容都需要手動干預(yù)
集群(直連型)
從redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用無中心結(jié)構(gòu),每個節(jié)點保存數(shù)據(jù)和整個集群狀態(tài),每個節(jié)點都和其他所有節(jié)點連接。
特點:
1、無中心架構(gòu)(不存在哪個節(jié)點影響性能瓶頸),少了 proxy 層。
2、數(shù)據(jù)按照 slot 存儲分布在多個節(jié)點,節(jié)點間數(shù)據(jù)共享,可動態(tài)調(diào)整數(shù)據(jù)分布。
3、可擴(kuò)展性,可線性擴(kuò)展到 1000 個節(jié)點,節(jié)點可動態(tài)添加或刪除。
4、高可用性,部分節(jié)點不可用時,集群仍可用。通過增加 Slave 做備份數(shù)據(jù)副本
5、實現(xiàn)故障自動 failover,節(jié)點之間通過 gossip 協(xié)議交換狀態(tài)信息,用投票機(jī)制完成 Slave到 Master 的角色提升。
缺點:
1、資源隔離性較差,容易出現(xiàn)相互影響的情況。
2、數(shù)據(jù)通過異步復(fù)制,不保證數(shù)據(jù)的強(qiáng)一致性
55、Redis AOF文件過大?AOF重寫的作用?
隨著命令不斷的寫入數(shù)據(jù),AOF文件會越來越大。為了解決這個問題,redis 引入了 AOF文件重寫機(jī)制,以便壓縮 AOF體積 ,更小的 AOF文件可以更快的被redis加載
從 Redis 2.4開始, AOF重寫由 Redis自行觸發(fā), 可以使用BGREWRITEAOF手動觸發(fā)重寫操作
AOF重寫的作用
減少磁盤占用量 、加速恢復(fù)速度
56、Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)
簡單動態(tài)字符串 simple dynamic string,SDS
鏈表
字典 又稱為符號表或者關(guān)聯(lián)數(shù)組、或映射(map)
跳躍表 skiplist
整數(shù)集合 intset
壓縮列表 ziplist
57、Redis過期key處理策略
Redis中有個設(shè)置時間過期的功能,即對存儲在 redis 數(shù)據(jù)庫中的值可以設(shè)置一個過期時間。作為一個緩存數(shù)據(jù)庫,這是非常實用的。如項目中的 token 或者一些登錄信息,尤其是短信驗證碼都是有時間限制的,按照傳統(tǒng)的數(shù)據(jù)庫處理方式,一般都是自己判斷過期,這樣無疑會嚴(yán)重影響項目性能。
操作set key 的時候,都可以給一個 expire time,就是過期時間,通過過期時間可以指定這個 key可以存活的時間。
如果假設(shè)你設(shè)置了一批 key 只能存活1個小時,那么接下來1小時后,redis是怎么對這批key進(jìn)行刪除的?
定期刪除 + 惰性刪除 ? ?通過名字大概就能猜出這兩個刪除方式的意思了。
定期刪除:redis默認(rèn)是每隔 100ms 就隨機(jī)抽取一些設(shè)置了過期時間的key,檢查其是否過期,如果過期就刪除。注意這里是隨機(jī)抽取的。為什么要隨機(jī)呢?你想一想假如 redis 存了幾十萬個 key ,每隔100ms就遍歷所有的設(shè)置過期時間的 key 的話,就會給 CPU 帶來很大的負(fù)載!
惰性刪除 :定期刪除可能會導(dǎo)致很多過期 key 到了時間并沒有被刪除掉。所以就有了惰性刪除。假如你的過期 key,靠定期刪除沒有被刪除掉,還停留在內(nèi)存里,除非你的系統(tǒng)去查一下那個 key,才會被redis給刪除掉。這就是所謂的惰性刪除,也是夠懶的哈!
僅僅通過設(shè)置過期時間還是有問題的。想一下:如果定期刪除漏掉了很多過期 key,然后也沒及時去查,也就沒走惰性刪除,此時會怎么樣?如果大量過期key堆積在內(nèi)存里,導(dǎo)致redis內(nèi)存塊耗盡了。怎么解決這個問題呢?
58、Redis事務(wù)
Redis通過 MULTI、EXEC、WATCH等命令來實現(xiàn)事務(wù)(transaction)功能。事務(wù)提供了一種將多個命令請求打包,然后一次性、按順序地執(zhí)行多個命令的機(jī)制,并且在事務(wù)執(zhí)行期間,服務(wù)器不會中斷事務(wù)而改去執(zhí)行其他客戶端的命令請求,它會將事務(wù)中的所有命令都執(zhí)行完畢,然后才去處理其他客戶端的命令請求。
在傳統(tǒng)的關(guān)系式數(shù)據(jù)庫中,常常用ACID性質(zhì)來檢驗事務(wù)功能的可靠性和安全性。在 Redis中,事務(wù)總是具有原子性(Atomicity)、一致性(Consistency)和隔離性(Isolation),并且當(dāng) Redis 運(yùn)行在某種特定的持久化模式下時,事務(wù)也具有持久性(Durability)。
59、如何保證緩存與數(shù)據(jù)庫雙寫時的數(shù)據(jù)一致性
如果不是嚴(yán)格要求“緩存和數(shù)據(jù)庫”必須保證一致性的話,最好不要做這個方案:即 讀請求和寫請求串行化,串到一個內(nèi)存隊列里面去。串行化可以保證一定不會出現(xiàn)不一致的情況,但會導(dǎo)致系統(tǒng)吞吐量大幅度降低。
解決這個問題的最經(jīng)典的模式,就是Cache Aside Pattern。
Cache Aside Pattern:
讀的時候先讀緩存,如果緩存不存在的話就讀數(shù)據(jù)庫,取出數(shù)據(jù)庫后更新緩存;如果存在的話直接讀取緩存的信息。
寫的時候,先更新數(shù)據(jù)庫,再刪除緩存。
說到這個問題,又會出現(xiàn)很多問題:
為什么是刪除緩存,而不是更新緩存?
為什么是先更新數(shù)據(jù)庫,再刪除緩存?不是先刪除緩存,再更新數(shù)據(jù)庫?
寫的時候為什么是刪除緩存不是更新緩存?
很多時候復(fù)雜的緩存場景,緩存不是僅僅從數(shù)據(jù)庫中取出來的值。可能是關(guān)聯(lián)多張表的數(shù)據(jù)并通過計算才是緩存需要的值。并且,更新緩存的代價有時候很高。對于需要頻繁寫操作,而讀操作很少的時候,每次進(jìn)行數(shù)據(jù)庫的修改,緩存也要隨之更新,會造成系統(tǒng)吞吐的下降,但此時緩存并不會被頻繁訪問到,用到的緩存才去算緩存。
刪除緩存而不是更新緩存,是一種懶加載的思想,不是每次都重復(fù)更新緩存,只有用到的時候才去更新緩存,同時即使有大量的讀請求,實際也就更新了一次,后面的請求不會重復(fù)讀。
Cache Aside Pattern存在的問題
問題:先更新數(shù)據(jù)庫,再刪除緩存,如果更新緩存失敗了,導(dǎo)致數(shù)據(jù)庫中是新數(shù)據(jù),緩存中是舊數(shù)據(jù),就出現(xiàn)數(shù)據(jù)不一致的問題。
解決思路:先刪除緩存,再更新數(shù)據(jù)庫。
緩存刪除失敗:如果緩存刪除失敗,那么數(shù)據(jù)庫信息沒有被修改,保持了數(shù)據(jù)的一致性;
緩存刪除成功,數(shù)據(jù)庫更新失敗:此時數(shù)據(jù)庫里的是舊數(shù)據(jù),緩存是空的,查詢時發(fā)現(xiàn)緩存不存在,就查詢數(shù)據(jù)庫并更新緩存,數(shù)據(jù)保持一致。問題:上面的方案存在不足,如果刪除完緩存更新數(shù)據(jù)庫時,如果一個請求過來查詢數(shù)據(jù),緩存不存在,就查詢數(shù)據(jù)庫的舊數(shù)據(jù),更新舊數(shù)據(jù)到緩存中。隨后數(shù)據(jù)更新完成,修改了數(shù)據(jù)庫的數(shù)據(jù),此時緩存和數(shù)據(jù)庫的數(shù)據(jù)就會出現(xiàn)不一致了。高并發(fā)下會出現(xiàn)這種數(shù)據(jù)庫+緩存不一致的情況。如果不采用給緩存設(shè)置過期時間策略,該數(shù)據(jù)永遠(yuǎn)都是臟數(shù)據(jù)。
解決方案:采用雙刪除策略。寫請求先刪除緩存,再去更新數(shù)據(jù)庫,等待一段時間后異步刪除緩存。這樣可以保證在讀取錯誤數(shù)據(jù)時能及時被修正過來。
還有一種策略,就是:寫請求先修改緩存為指定值,然后再去更新數(shù)據(jù)庫,再更新緩存。讀請求過來后,會先讀緩存,判斷是指定值后就進(jìn)入循環(huán)讀取狀態(tài),等到寫請求更新緩存。如果循環(huán)超時就去數(shù)據(jù)庫讀取數(shù)據(jù),更新緩存。
這種方案保證了讀寫的一致性,但由于讀請求等待寫請求的完成,會降低系統(tǒng)的吞吐量。
60、何解決Redis的并發(fā)競爭Key問題
所謂Redis的并發(fā)競爭Key的問題也就是多個系統(tǒng)同時對一個key進(jìn)行操作,但是最后執(zhí)行的順序與期望的順序一致,這樣也就導(dǎo)致了結(jié)果的不同!
推薦一種方案:分布式鎖(zookeeper和redis都可以實現(xiàn)分布式鎖)。如果不存在Redis的并發(fā)競爭Key問題,不要使用分布式鎖,這樣會影響性能
基于zookeeper臨時有序節(jié)點可以實現(xiàn)的分布式鎖。大致思想為:每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應(yīng)的指定節(jié)點的目錄下,生成一個唯一的瞬時有序節(jié)點。判斷是否獲取鎖的方式很簡單,只需要判斷有序節(jié)點中序號最小的一個。當(dāng)釋放鎖的時候,只需將這個瞬時節(jié)點刪除即可。同時,其可以避免服務(wù)宕機(jī)導(dǎo)致的鎖無法釋放,而產(chǎn)生的死鎖問題。完成業(yè)務(wù)流程后,刪除對應(yīng)的子節(jié)點釋放鎖。
在實踐中,當(dāng)然是從以可靠性為主; 所以首推Zookeeper。
61、Redis分布式鎖的注意事項
互斥性。在任意時刻,只有一個客戶端能持有鎖。
不會發(fā)生死鎖。即使有一個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保證后續(xù)其他客戶端能加鎖。
具有容錯性。只要大部分的Redis節(jié)點正常運(yùn)行,客戶端就可以加鎖和解鎖。
解鈴還須系鈴人。加鎖和解鎖必須是同一個客戶端,客戶端自己不能把別人加的鎖給解了。
業(yè)務(wù)執(zhí)行時間超過鎖的有效期時,如何有效進(jìn)行延遲鎖的有效期。添加一個看門狗線程,進(jìn)行鎖有效期檢測
62、假如Redis里面有1億個key,其中有10w個key是以某個固定的已知的前綴開頭的,如果將它們?nèi)空页鰜恚?/span>
使用keys指令可以掃出指定模式的key列表:keys pre*
63、如果這個redis正在給線上的業(yè)務(wù)提供服務(wù),那使用keys指令會有什么問題?
這個時候你要回答redis關(guān)鍵的一個特性:redis的單線程的。keys指令會導(dǎo)致線程阻塞一段時間,線上服務(wù)會停頓,直到指令執(zhí)行完畢,服務(wù)才能恢復(fù)。
這個時候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key列表,但是會有一定的重復(fù)概率,在客戶端做一次去重就可以了,但是整體所花費(fèi)的時間會比直接用keys指令長。
64、 使用過Redis做異步隊列么,你是怎么用的?
一般使用list結(jié)構(gòu)作為隊列,rpush生產(chǎn)消息,lpop消費(fèi)消息。當(dāng)lpop沒有消息的時候,要適當(dāng)sleep一會再重試。
如果對方追問可不可以不用sleep呢?list還有個指令叫blpop,在沒有消息的時候,它會阻塞住直到消息到來。
如果對方追問能不能生產(chǎn)一次消費(fèi)多次呢?使用pub/sub主題訂閱者模式,可以實現(xiàn)1:N的消息隊列。
如果對方追問pub/sub有什么缺點?在消費(fèi)者下線的情況下,生產(chǎn)的消息會丟失,得使用專業(yè)的消息隊列如rabbitmq等。redis中pub/sub缺陷
65、如果對方追問redis如何實現(xiàn)延時隊列?
使用有序集合,拿時間戳作為score,消息內(nèi)容作為key調(diào)用zadd來生產(chǎn)消息,消費(fèi)者用zrangebyscore指令獲取N秒之前的數(shù)據(jù)輪詢進(jìn)行處理。
66、如果有大量的key需要設(shè)置同一時間過期,一般需要注意什么
如果大量的key過期時間設(shè)置的過于集中,到過期的那個時間點,redis可能會出現(xiàn)短暫的卡頓現(xiàn)象。一般需要在時間上加一個隨機(jī)值,使得過期時間分散一些。
67、 Redis如何做持久化的?
RDB做鏡像全量持久化,AOF做增量持久化。
RDB持久化也分兩種:SAVE和BGSAVE。
SAVE是阻塞式的RDB持久化,當(dāng)執(zhí)行這個命令時redis的主進(jìn)程把內(nèi)存里的數(shù)據(jù)庫狀態(tài)寫入到RDB文件中,直到該文件創(chuàng)建完畢的這段時間內(nèi)redis將不能處理任何命令請求;1 BGSAVE屬于非阻塞式的持久化,它會創(chuàng)建一個子進(jìn)程專門去把內(nèi)存中的數(shù)據(jù)庫狀態(tài)寫入RDB文件里,同時主進(jìn)程還可以處理來自客戶端的命令請求。
但子進(jìn)程基本是復(fù)制的父進(jìn)程,這等于兩個相同大小的redis進(jìn)程在系統(tǒng)上運(yùn)行,會造成內(nèi)存使用率的大幅增加。
AOF的持久化是通過命令追加、文件寫入和文件同步三個步驟實現(xiàn)的。
當(dāng)reids開啟AOF后(redis備份方式默認(rèn)是RDB);
服務(wù)端每執(zhí)行一次寫操作(如set、sadd、rpush)就會把該條命令追加到一個單獨的AOF緩沖區(qū)的末尾,這就是命令追加;
然后把AOF緩沖區(qū)的內(nèi)容寫入AOF文件里。看上去第二步就已經(jīng)完成AOF持久化了那第三步是干什么的呢?這就需要從系統(tǒng)的文件寫入機(jī)制說起:一般我們現(xiàn)在所使用的操作系統(tǒng),為了提高文件的寫入效率,都會有一個寫入策略,即當(dāng)你往
硬盤寫入數(shù)據(jù)時,操作系統(tǒng)不是實時的將數(shù)據(jù)寫入硬盤,而是先把數(shù)據(jù)暫時的保存在一個內(nèi)存緩沖區(qū)里,等到這個內(nèi)存緩沖區(qū)的空間被填滿或者是超過了設(shè)定的時限后才會真正的把緩沖區(qū)內(nèi)的數(shù)據(jù)寫入硬盤中。也就是說當(dāng)redis進(jìn)行到第二
步文件寫入的時候,從用戶的角度看是已經(jīng)把AOF緩沖區(qū)里的數(shù)據(jù)寫入到AOF文件了,但對系統(tǒng)而言只不過是把AOF緩沖區(qū)的內(nèi)容放到了另一個內(nèi)存緩沖區(qū)里而已,之后redis還需要進(jìn)行文件同步把該內(nèi)存緩沖區(qū)里的數(shù)據(jù)真正寫入硬盤上
才算是完成了一次持久化。而何時進(jìn)行文件同步則是根據(jù)配置的appendfsync來進(jìn)行:appendfsync有三個選項:always、everysec和no:
68、Pipeline有什么好處,為什么要用pipeline?
可以將多次IO往返的時間縮減為一次,前提是pipeline執(zhí)行的指令之間沒有因果相關(guān)性。使用redis-benchmark進(jìn)行壓測的時候可以發(fā)現(xiàn)影響redis的QPS峰值的一個重要因素是pipeline批次指令的數(shù)目。
69、Redis的同步機(jī)制了解么?
Redis可以使用主從同步,從從同步。第一次同步時,主節(jié)點做一次bgsave,并同時將后續(xù)修改操作記錄到內(nèi)存buffer,待完成后將rdb文件全量同步到復(fù)制節(jié)點,復(fù)制節(jié)點接受完成后將rdb鏡像加載到內(nèi)存。
加載完成后,再通知主節(jié)點將期間修改的操作記錄同步到復(fù)制節(jié)點進(jìn)行重放就完成了同步過程。
70、是否使用過Redis集群,集群的原理是什么?
Redis Sentinal著眼于高可用,在master宕機(jī)時會自動將slave提升為master,繼續(xù)提供服務(wù)。
Redis Cluster著眼于擴(kuò)展性,在單個redis內(nèi)存不足時,使用Cluster進(jìn)行分片存儲。
71、使用redis有哪些好處?
速度快,因為數(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è)置過期時間,過期后將會自動刪除
72、redis相比memcached有哪些優(yōu)勢?Memcache與Redis的區(qū)別都有哪些?
優(yōu)勢
memcached所有的值均是簡單的字符串,redis作為其替代者,支持更為豐富的數(shù)據(jù)類型
redis的速度比memcached快很多
redis可以持久化其數(shù)據(jù)
區(qū)別
存儲方式 Memecache把數(shù)據(jù)全部存在內(nèi)存之中,斷電后會掛掉,數(shù)據(jù)不能超過內(nèi)存大小。Redis有部份存在硬盤上,這樣能保證數(shù)據(jù)的持久性。
數(shù)據(jù)支持類型 Memcache對數(shù)據(jù)類型支持相對簡單。Redis有復(fù)雜的數(shù)據(jù)類型。
使用底層模型不同 它們之間底層實現(xiàn)方式 以及與客戶端之間通信的應(yīng)用協(xié)議不一樣。Redis直接自己構(gòu)建了VM 機(jī)制 ,因為一般的系統(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會浪費(fèi)一定的時間去移動和請求。
73、redis常見性能問題和解決方案:
Master寫內(nèi)存快照,save命令調(diào)度rdbSave函數(shù),會阻塞主線程的工作,當(dāng)快照比較大時對性能影響是非常大的,會間斷性暫停服務(wù),所以Master最好不要寫內(nèi)存快照。
Master AOF持久化,如果不重寫AOF文件,這個持久化方式對性能的影響是最小的,但是AOF文件會不斷增大,AOF文件過大會影響Master重啟的恢復(fù)速度。
Master最好不要做任何持久化工作,包括內(nèi)存快照和AOF日志文件,特別是不要啟用內(nèi)存快照做持久化,如果數(shù)據(jù)比較關(guān)鍵,某個Slave開啟AOF備份數(shù)據(jù),策略為每秒同步一次。
Master調(diào)用BGREWRITEAOF重寫AOF文件,AOF在重寫的時候會占大量的CPU和內(nèi)存資源,導(dǎo)致服務(wù)load過高,出現(xiàn)短暫服務(wù)暫停現(xiàn)象。
Redis主從復(fù)制的性能問題,為了主從復(fù)制的速度和連接的穩(wěn)定性,Slave和Master最好在同一個局域網(wǎng)內(nèi)
74、為什么redis需要把所有數(shù)據(jù)放到內(nèi)存中?
Redis為了達(dá)到最快的讀寫速度將數(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ù)達(dá)到內(nèi)存限值后不能繼續(xù)插入新值。
75、Redis是單進(jìn)程單線程的
redis利用隊列技術(shù)將并發(fā)訪問變?yōu)榇性L問,消除了傳統(tǒng)數(shù)據(jù)庫串行控制的開銷。
76、redis的并發(fā)競爭問題如何解決?
Redis為單進(jìn)程單線程模式,采用隊列模式將并發(fā)訪問變?yōu)榇性L問。Redis本身沒有鎖的概念,Redis對于多個客戶端連接并不存在競爭,但是在Jedis客戶端對Redis進(jìn)行并發(fā)訪問時會發(fā)生連接超時、數(shù)據(jù)轉(zhuǎn)換錯誤、阻塞、客戶端關(guān)閉連接等問題,這些問題均是由于客戶端連接混亂造成。對此有2種解決方法:
客戶端角度,為保證每個客戶端間正常有序與Redis進(jìn)行通信,對連接進(jìn)行池化,同時對客戶端讀寫Redis操作采用內(nèi)部鎖synchronized。
+服務(wù)器角度,利用setnx實現(xiàn)鎖。
注:對于第一種,需要應(yīng)用程序自己處理資源的同步,可以使用的方法比較通俗,可以使用synchronized也可以使用lock;第二種需要用到Redis的setnx命令,但是需要注意一些問題。
77、redis事物的了解CAS(check-and-set 操作實現(xiàn)樂觀鎖 )?
和眾多其它數(shù)據(jù)庫一樣,Redis作為NoSQL數(shù)據(jù)庫也同樣提供了事務(wù)機(jī)制。在Redis中,MULTI/EXEC/DISCARD/WATCH這四個命令是我們實現(xiàn)事務(wù)的基石。相信對有關(guān)系型數(shù)據(jù)庫開發(fā)經(jīng)驗的開發(fā)者而言這一概念并不陌生,即便如此,我們還是會簡要的列出Redis中事務(wù)的實現(xiàn)特征:
在事務(wù)中的所有命令都將會被串行化的順序執(zhí)行,事務(wù)執(zhí)行期間,Redis不會再為其它客戶端的請求提供任何服務(wù),從而保證了事物中的所有命令被原子的執(zhí)行。
和關(guān)系型數(shù)據(jù)庫中的事務(wù)相比,在Redis事務(wù)中如果有某一條命令執(zhí)行失敗,其后的命令仍然會被繼續(xù)執(zhí)行。
可以通過MULTI命令開啟一個事務(wù),有關(guān)系型數(shù)據(jù)庫開發(fā)經(jīng)驗的人可以將其理解為"BEGIN TRANSACTION"語句。在該語句之后執(zhí)行的命令都將被視為事務(wù)之內(nèi)的操作,最后我們可以通過執(zhí)行
EXEC/DISCARD命令來提交/回滾該事務(wù)內(nèi)的所有操作。這兩個Redis命令可被視為等同于關(guān)系型數(shù)據(jù)庫中的COMMIT/ROLLBACK語句。在事務(wù)開啟之前,如果客戶端與服務(wù)器之間出現(xiàn)通訊故障并導(dǎo)致網(wǎng)絡(luò)斷開,其后所有待執(zhí)行的語句都將不會被服務(wù)器執(zhí)行。然而如果網(wǎng)絡(luò)中斷事件是發(fā)生在客戶端執(zhí)行EXEC命令之后,那么該事務(wù)中的所有命令都會被服務(wù)器執(zhí)行。
當(dāng)使用Append-Only模式時,Redis會通過調(diào)用系統(tǒng)函數(shù)write將該事務(wù)內(nèi)的所有寫操作在本次調(diào)用中全部寫入磁盤。然而如果在寫入的過程中出現(xiàn)系統(tǒng)崩潰,如電源故障導(dǎo)致的宕機(jī),那么此時也許只有部分?jǐn)?shù)據(jù)被寫入到磁盤,
而另外一部分?jǐn)?shù)據(jù)卻已經(jīng)丟失。Redis服務(wù)器會在重新啟動時執(zhí)行一系列必要的一致性檢測,一旦發(fā)現(xiàn)類似問題,就會立即退出并給出相應(yīng)的錯誤提示。此時,我們就要充分利用Redis工具包中提供的redis-check-aof工具,
該工具可以幫助我們定位到數(shù)據(jù)不一致的錯誤,并將已經(jīng)寫入的部分?jǐn)?shù)據(jù)進(jìn)行回滾。修復(fù)之后我們就可以再次重新啟動Redis服務(wù)器了。
78、 redis持久化的幾種方式
快照(snapshots)
缺省情況情況下,Redis把數(shù)據(jù)快照存放在磁盤上的二進(jìn)制文件中,文件名為dump.rdb。你可以配置Redis的持久化策略,例如數(shù)據(jù)集中每N秒鐘有超過M次更新,就將數(shù)據(jù)寫入磁盤;或者你可以手工調(diào)用命令SAVE或BGSAVE。
工作原理:Redis forks. 子進(jìn)程開始將數(shù)據(jù)寫到臨時RDB文件中。當(dāng)子進(jìn)程完成寫RDB文件,用新文件替換老文件。這種方式可以使Redis使用copy-on-write技術(shù)。
AOF
快照模式并不健壯,當(dāng)系統(tǒng)停止,或者無意中Redis被kill掉,最后寫入Redis的數(shù)據(jù)就會丟失。這對某些應(yīng)用也許不是大問題,但對于要求高可靠性的應(yīng)用來說,Redis就不是一個合適的選擇。Append-only文件模式是另一種選擇。你可以在配置文件中打開AOF模式。
虛擬內(nèi)存方式
當(dāng)你的key很小而value很大時,使用VM的效果會比較好.因為這樣節(jié)約的內(nèi)存比較大. 當(dāng)你的key不小時,可以考慮使用一些非常方法將很大的key變成很大的value,比如你可以考慮將key,value組合成一個新的value. vm-max-threads這個參數(shù),可以設(shè)置訪問swap文件的線程數(shù),設(shè)置最好不要超過機(jī)器的核數(shù),如果設(shè)置為0,那么所有對swap文件的操作都是串行的.可能會造成比較長時間的延遲,但是對數(shù)據(jù)完整性有很好的保證.

掃碼二維碼
獲取更多精彩
Java樂園

