Redis 常見問題

創(chuàng)新互聯(lián)從2013年成立,先為天等等服務建站,天等等地企業(yè),進行企業(yè)商務咨詢服務。為天等企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。
落葉他鄉(xiāng)樹,寒燈獨夜人。
一、 什么是Redis?
- Redis 是一個使用 C 語言寫成的,開源的高性能key-value非關系緩存數(shù)據(jù)庫;
- Redis的數(shù)據(jù)都基于緩存的,所以很快,每秒可以處理超過 10萬次讀寫操作;
- Redis也可以實現(xiàn)數(shù)據(jù)寫入磁盤中,保證了數(shù)據(jù)的安全不丟失,而且Redis的操作是原子性的。
二、 Redis有哪些優(yōu)缺點?
優(yōu)點
- 讀寫性能優(yōu)異, Redis能讀的速度是110000次/s,寫的速度是81000次/s。
- 支持數(shù)據(jù)持久化,支持AOF和RDB兩種持久化方式。
- 支持事務,Redis的所有操作都是原子性的,同時Redis還支持對幾個操作合并后的原子性執(zhí)行。
- 數(shù)據(jù)結(jié)構(gòu)豐富,除了支持string類型的value外還支持hash、set、zset、list等數(shù)據(jù)結(jié)構(gòu)。
- 支持主從復制,主機 會自動將數(shù)據(jù)同步到 從機,可以進行讀寫分離。
- 豐富的特性:可用于緩存,消息,按key設置過期時間,過期后將會自動刪除。
缺點
- 數(shù)據(jù)庫容量受到物理內(nèi)存的限制,不能用作海量數(shù)據(jù)的高性能讀寫,因此Redis適合的場景主要局限在較小數(shù)據(jù)量的高性能操作和運算上。
- Redis 不具備自動容錯和恢復功能,主機從機的宕機都會導致前端部分讀寫請求失敗,需要等待機器重啟或者手動切換前端的IP才能恢復。
- 主機宕機,宕機前有部分數(shù)據(jù)未能及時同步到從機,切換IP后還會引入數(shù)據(jù)不一致的問題,降低了系統(tǒng)的可用性。
- Redis 較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜。為避免這一問題,運維人員在系統(tǒng)上線時必須確保有足夠的空間,這對資源造成了很大的浪費。
三、使用redis有哪些好處?
- (1) 速度快,因為數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢就是查找和操作的時間復雜度都很低
- (2) 支持豐富數(shù)據(jù)類型,支持string,list,set,sorted set,hash
- (3) 支持事務,操作都是原子性,所謂的原子性就是對數(shù)據(jù)的更改要么全部執(zhí)行,要么全部不執(zhí)行
- (4) 豐富的特性:可用于緩存,消息,按key設置過期時間,過期后將會自動刪除
四、 為什么要用 Redis ?為什么要用緩存?
主要從“高性能”和“高并發(fā)”這兩點來看待這個問題。
高性能
假如用戶第一次訪問數(shù)據(jù)庫中的某些數(shù)據(jù)。這個過程會比較慢,因為是從硬盤上讀取的。將該用戶訪問的數(shù)據(jù)存在數(shù)緩存中,這樣下一次再訪問這些數(shù)據(jù)的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內(nèi)存,所以速度相當快。如果數(shù)據(jù)庫中的對應數(shù)據(jù)改變的之后,同步改變緩存中相應的數(shù)據(jù)即可!
高并發(fā)
直接操作緩存能夠承受的請求是遠遠大于直接訪問數(shù)據(jù)庫的,所以我們可以考慮把數(shù)據(jù)庫中的部分數(shù)據(jù)轉(zhuǎn)移到緩存中去,這樣用戶的一部分請求會直接到緩存這里而不用經(jīng)過數(shù)據(jù)庫。
五、為什么要用 Redis 而不用 map/guava 做緩存?
- 緩存分為本地緩存和分布式緩存。以 Java 為例,使用自帶的 map 或者 guava 實現(xiàn)的是本地緩存,最主要的特點是輕量以及快速,生命周期隨著 jvm 的銷毀而結(jié)束,并且在多實例的情況下,每個實例都需要各自保存一份緩存,緩存不具有一致性。
- 使用 redis 或 memcached 之類的稱為分布式緩存,在多實例的情況下,各實例共用一份緩存數(shù)據(jù),緩存具有一致性。缺點是需要保持 redis 或 memcached服務的高可用,整個程序架構(gòu)上較為復雜。
六、Redis為什么這么快?
- 1、完全基于內(nèi)存,絕大部分請求是純粹的內(nèi)存操作,非常快速。數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap 的優(yōu)勢就是查找和操作的時間復雜度都是O(1);
- 2、數(shù)據(jù)結(jié)構(gòu)簡單,對數(shù)據(jù)操作也簡單,Redis 中的數(shù)據(jù)結(jié)構(gòu)是專門進行設計的;
- 3、采用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換
- 而消耗 CPU,不用去考慮各種鎖的問題(單線程不存在多個線程同時訪問同一資源),不存在加鎖釋放鎖操作,沒有因為可能出現(xiàn)死鎖而導致的性能消耗;
- 4、使用多路 I/O 復用模型,非阻塞 IO;
- 5、使用底層模型不同,它們之間底層實現(xiàn)方式以及與客戶端之間通信的應用協(xié)議不一樣,Redis直接自己構(gòu)建了 VM 機制 ,因為一般的系統(tǒng)調(diào)用系統(tǒng)函數(shù)的話,會浪費一定的時間去移動和請求;
七、Redis有哪些數(shù)據(jù)類型?
Redis除了最常用的5種基本數(shù)據(jù)類型,包括String,List,Set,Zset,Hash,還有geospatial、hyperloglog和bitmap 三種特殊數(shù)據(jù)類型。https://www.cnblogs.com/taojietaoge/p/15915947.html(Redis數(shù)據(jù)類型)
八、 Redis的應用場景
計數(shù)器
可以對 String 進行自增自減運算,從而實現(xiàn)計數(shù)器功能。Redis 這種內(nèi)存型數(shù)據(jù)庫的讀寫性能非常高,很適合存儲頻繁讀寫的計數(shù)量。
緩存
將熱點數(shù)據(jù)放到內(nèi)存中,設置內(nèi)存的最大使用量以及淘汰策略來保證緩存的命中率。
會話緩存
可以使用 Redis 來統(tǒng)一存儲多臺應用服務器的會話信息。當應用服務器不再存儲用戶的會話信息,也就不再具有狀態(tài),一個用戶可以請求任意一個應用服務器,從而更容易實現(xiàn)高可用性以及可伸縮性。
全頁緩存(FPC)
除基本的會話token之外,Redis還提供很簡便的FPC平臺。以Magento為例,Magento提供一個插件來使用Redis作為全頁緩存后端。此外,對WordPress的用戶來說,Pantheon有一個非常好的插件 wpredis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面。
查找表
例如 DNS 記錄就很適合使用 Redis 進行存儲。查找表和緩存類似,也是利用了 Redis 快速的查找特性。但是查找表的內(nèi)容不能失效,而緩存的內(nèi)容可以失效,因為緩存不作為可靠的數(shù)據(jù)來源。
消息隊列(發(fā)布/訂閱功能)
List 是一個雙向鏈表,可以通過 lpush 和 rpop 寫入和讀取消息。不過最好使用 Kafka、RabbitMQ 等消息中間件。
分布式鎖實現(xiàn)
在分布式場景下,無法使用單機環(huán)境下的鎖來對多個節(jié)點上的進程進行同步。可以使用 Redis 自帶的 SETNX 命令實現(xiàn)分布式鎖,除此之外,還可以使用官方提供的RedLock 分布式鎖實現(xiàn)。
其它
Set 可以實現(xiàn)交集、并集等操作,從而實現(xiàn)共同好友等功能。ZSet 可以實現(xiàn)有序性操作,從而實現(xiàn)排行榜等功能。
九、什么是Redis持久化?
持久化就是把內(nèi)存的數(shù)據(jù)寫到磁盤中去,防止服務宕機導致內(nèi)存數(shù)據(jù)丟失。
十、 Redis 的持久化機制是什么?各自的優(yōu)缺點?
Redis 提供兩種持久化機制
RDB(默認) 和
AOF 機制。
RDB
- RDB是Redis DataBase縮寫快照。
- RDB是Redis默認的持久化方式。按照一定的時間將內(nèi)存的數(shù)據(jù)以快照的形式保存到硬盤中,對應產(chǎn)生的數(shù)據(jù)文件為dump.rdb。通過配置文件中的save參數(shù)來定義快照的周期。
優(yōu)點
- 1、只有一個文件 dump.rdb,方便持久化。
- 2、容災性好,一個文件可以保存到安全的磁盤。
- 3、性能最大化,fork 子進程來完成寫操作,讓主進程繼續(xù)處理命令,所以是 IO 最大化。使用單獨子進程來進行持久化,主進程不會進行任何 IO 操作,保證了 redis 的高性能。
- 4.相對于數(shù)據(jù)集大時,比 AOF 的啟動效率更高。
缺點
- 1、數(shù)據(jù)安全性低。RDB 是間隔一段時間進行持久化,如果持久化之間 redis 發(fā)生故障,會發(fā)生數(shù)據(jù)丟失。所以這種方式更適合數(shù)據(jù)要求不嚴謹?shù)臅r候)。
- 2、AOF(Append-only file)持久化方式: 是指所有的命令行記錄以 redis 命令請 求協(xié)議的格式完全持久化存儲)保存為 aof 文件。
AOF
- AOF持久化(即Append Only File持久化),則是將Redis執(zhí)行的每次寫命令記錄到單獨的日志文件中,當重啟Redis會重新將持久化的日志中文件恢復數(shù)據(jù)。
- 當兩種方式同時開啟時,數(shù)據(jù)恢復Redis會優(yōu)先選擇AOF恢復。
優(yōu)點
- 1、數(shù)據(jù)安全,aof 持久化可以配置 appendfsync 屬性,有 always,每進行一次 命令操作就記錄到 aof 文件中一次。
- 2、通過 append 模式寫文件,即使中途服務器宕機,可以通過 redis-check-aof 工具解決數(shù)據(jù)一致性問題。
- 3、AOF 機制的 rewrite 模式。AOF 文件沒被 rewrite 之前(文件過大時會對命令 進行合并重寫),可以刪除其中的某些命令(比如誤操作的 flushall))。
缺點
- 1、AOF 文件比 RDB 文件大,且恢復速度慢。
- 2、數(shù)據(jù)集大的時候,比 rdb 啟動效率低。
倆種持久化的優(yōu)缺點是什么?
- AOF文件比RDB更新頻率高,優(yōu)先使用AOF還原數(shù)據(jù)。
- AOF比RDB更安全也更大。
- RDB性能比AOF好。
- 如果兩個都配了優(yōu)先加載AOF。
十一、如何選擇合適的持久化方式?
- 一般來說,如果想達到足以媲美PostgreSQL的數(shù)據(jù)安全性,你應該同時使用兩種持久化功能。在這種情況下,當 Redis 重啟的時候會優(yōu)先載入AOF文件來恢復原始的數(shù)據(jù),因為在通常情況下AOF文件保存的數(shù)據(jù)集要比RDB文件保存的數(shù)據(jù)集要完整。如果你非常關心你的數(shù)據(jù),但仍然可以承受數(shù)分鐘以內(nèi)的數(shù)據(jù)丟失,那么你可以只使用RDB持久化。
- 有很多用戶都只使用AOF持久化,但并不推薦這種方式,因為定時生成RDB快照(snapshot)非常便于進行數(shù)據(jù)庫備份,并且 RDB 恢復數(shù)據(jù)集的速度也要比AOF恢復的速度要快,除此之外,使用RDB還可以避免AOF程序的bug。
- 如果你只希望你的數(shù)據(jù)在服務器運行的時候存在,你也可以不使用任何持久化方式。
Redis持久化數(shù)據(jù)和緩存怎么做擴容?
- 如果Redis被當做緩存使用,使用一致性哈希實現(xiàn)動態(tài)擴容縮容。
- 如果Redis被當做一個持久化存儲使用,必須使用固定的keys-to-nodes映射關系,節(jié)點的數(shù)量一旦確定不能變化。否則的話(即Redis節(jié)點需要動態(tài)變化的情況),必須使用可以在運行時進行數(shù)據(jù)再平衡的一套系統(tǒng),而當前只有Redis集群可以做到這樣。
十二、Redis的過期鍵的刪除策略
過期策略通常有以下三種:定時過期、惰性過期和定期過期。
定時過期
- 每個設置過期時間的key都需要創(chuàng)建一個定時器,到過期時間就會立即清除。該策略可以立即清除過期的數(shù)據(jù),對內(nèi)存很友好;
- 但是會占用大量的CPU資源去處理過期的數(shù)據(jù),從而影響緩存的響應時間和吞吐量。
惰性過期
- 只有當訪問一個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)的平衡效果。 (expires字典會保存所有設置了過期時間的key的過期時間數(shù)據(jù),其中,key是指向鍵空間中的某個鍵的指針,value是該鍵的毫秒精度的UNIX時間戳表示的過期時間。鍵空間是指該Redis集群中保存的所有鍵。)
- Redis中同時使用了惰性過期和定期過期兩種過期策略。
十三、Redis key的過期時間和永久有效分別怎么設置?
通過 expire 和 persist 命令。
十四、我們知道通過expire來設置key 的過期時間,那么對過期的數(shù)據(jù)怎么處理呢?
除了緩存服務器自帶的緩存失效策略之外(Redis默認的有6中策略可供選擇),我們還可以根據(jù)具體的業(yè)務需求進行自定義的緩存淘汰,常見的策略有兩種:
- 1、定時去清理過期的緩存;
- 2、當有用戶請求過來時,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統(tǒng)得到新數(shù)據(jù)并更新緩存。
兩者各有優(yōu)劣,第一種的缺點是維護大量緩存的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效,邏輯相對比較復雜!具體用哪種方案,大家可以根據(jù)自己的應用場景來權(quán)衡。
十五、MySQL里有2000w數(shù)據(jù),redis中只存20w的數(shù)據(jù),如何保證redis中的數(shù)據(jù)都是熱點數(shù)據(jù)?
redis內(nèi)存數(shù)據(jù)集大小上升到一定大小的時候,就會施行數(shù)據(jù)淘汰策略。
十六、Redis的內(nèi)存淘汰策略有哪些?
Redis的內(nèi)存淘汰策略是指在Redis的用于緩存的內(nèi)存不足時,怎么處理需要新寫入且需要申請額外空間的數(shù)據(jù)。
全局的鍵空間選擇性移除
- noeviction:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,新寫入操作會報錯。
- allkeys-lru:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在鍵空間中,移除最近最少使用的key。(這個是最常用的)
- allkeys-random:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在鍵空間中,隨機移除某個key。
設置過期時間的鍵空間選擇性移除
- volatile-lru:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在設置了過期時間的鍵空間中,移除最近最少使用的key。
- volatile-random:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在設置了過期時間的鍵空間中,隨機移除某個key。
- volatile-ttl:當內(nèi)存不足以容納新寫入數(shù)據(jù)時,在設置了過期時間的鍵空間中,有更早過期時間的key優(yōu)先移除。
總結(jié)Redis的內(nèi)存淘汰策略的選取并不會影響過期的key的處理。內(nèi)存淘汰策略用于處理內(nèi)存不足時的需要申請額外空間的數(shù)據(jù);過期策略用于處理過期的緩存數(shù)據(jù)。
十七、Redis主要消耗什么物理資源?
內(nèi)存。
十八、Redis的內(nèi)存用完了會發(fā)生什么?
如果達到設置的上限,Redis的寫命令會返回錯誤信息(但是讀命令還可以正常返回。)或者可以配置內(nèi)存淘汰機制,當Redis達到內(nèi)存上限時會沖刷掉舊的內(nèi)容。
十九、Redis如何做內(nèi)存優(yōu)化?
- 可以好好利用Hash、list、sorted set、set等集合類型數(shù)據(jù),因為通常情況下很多小的Key-Value可以用更緊湊的方式存放到一起。
- 盡可能使用散列表(hashes),散列表(是說散列表里面存儲的數(shù)少)使用的內(nèi)存非常小,所以你應該盡可能的將你的數(shù)據(jù)模型抽象到一個散列表里面。
- 比如你的web系統(tǒng)中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設置單獨的key,而是應該把這個用戶的所有信息存儲到一張散列表里面。
二十、Redis線程模型
- Redis基于Reactor模式開發(fā)了網(wǎng)絡事件處理器,這個處理器被稱為文件事件處理器(file event handler)。它的組成結(jié)構(gòu)為4部分:多個套接字、IO多路復用程序、文件事件分派器、事件處理器。
- 因為文件事件分派器隊列的消費是單線程的,所以Redis才叫單線程模型。
- 文件事件處理器使用 I/O 多路復用(multiplexing)程序來同時監(jiān)聽多個套接字,并根據(jù)套接字目前執(zhí)行的任務來為套接字關聯(lián)不同的事件處理器。
- 當被監(jiān)聽的套接字準備好執(zhí)行連接應答(accept)、讀取(read)、寫入(write)、關閉(close)等操作時,與操作相對應的文件事件就會產(chǎn)生, 這時文件事件處理器就會調(diào)用套接字之前關聯(lián)好的事件處理器來處理這些事件。
- 雖然文件事件處理器以單線程方式運行,但通過使用 I/O 多路復用程序來監(jiān)聽多個套接字,文件事件處理器既實現(xiàn)了高性能的網(wǎng)絡通信模型,又可以很好地與 redis 服務器中其他同樣以單線程方式運行的模塊進行對接,這保持了 Redis 內(nèi)部單線程設計的簡單性。
二十一、什么是事務?
- 事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執(zhí)行。事務在執(zhí)行的過程中,不會被其他客戶端發(fā)送來的命令請求所打斷。
- 事務是一個原子操作:事務中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行。
二十二、Redis事務的概念
- Redis 事務的本質(zhì)是通過MULTI、EXEC、WATCH等一組命令的集合。事務支持一次執(zhí)行多個命令,一個事務中所有命令都會被序列化。
- 在事務執(zhí)行過程,會按照順序串行化執(zhí)行隊列中的命令,其他客戶端提交的命令請求不會插入到事務執(zhí)行命令序列中。
- 總結(jié)說:redis事務就是一次性、順序性、排他性的執(zhí)行一個隊列中的一系列命令。
二十三、Redis事務的三個階段
- 1. 事務開始 MULTI
- 2. 命令入隊
- 3. 事務執(zhí)行 EXEC
事務執(zhí)行過程中,如果服務端收到有EXEC、DISCARD、WATCH、MULTI之外的請求,將會把請求放入隊列中排隊。
二十四、Redis事務相關命令
Redis事務功能是通過MULTI、EXEC、DISCARD和WATCH 四個原語實現(xiàn)的,Redis會將一個事務中的所有命令序列化,然后按順序執(zhí)行。
- 1. redis 不支持回滾,“Redis 在事務失敗時不進行回滾,而是繼續(xù)執(zhí)行余下的命令”, 所以 Redis 的內(nèi)部可以保持簡單且快速。
- 2. 如果在一個事務中的命令出現(xiàn)錯誤,那么所有的命令都不會執(zhí)行;
- 3. 如果在一個事務中出現(xiàn)運行錯誤,那么正確的命令會被執(zhí)行。
- WATCH:命令是一個樂觀鎖,可以為 Redis 事務提供 check-and-set (CAS)行為。 可以監(jiān)控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之后的事務就不會執(zhí)行,監(jiān)控一直持續(xù)到EXEC命令。
- MULTI:命令用于開啟一個事務,它總是返回OK。 MULTI執(zhí)行之后,客戶端可以繼續(xù)向服務器發(fā)送任意多條命令,這些命令不會立即被執(zhí)行,而是被放到一個隊列中,當EXEC:命令被調(diào)用時,所有隊列中的命令才會被執(zhí)行。
- EXEC:執(zhí)行所有事務塊內(nèi)的命令。返回事務塊內(nèi)所有命令的返回值,按命令執(zhí)行的先后順序排列。當操作被打斷時,返回空值 nil 。
- DISCARD:通過調(diào)用DISCARD,客戶端可以清空事務隊列,并放棄執(zhí)行事務, 并且客戶端會從事務狀態(tài)中退出。
- UNWATCH:命令可以取消watch對所有key的監(jiān)控。
二十五、事務管理(ACID)概述
原子性(Atomicity)原子性是指事務是一個不可分割的工作單位,事務中的操作要么都發(fā)生,要么都不發(fā)生。
一致性(Consistency)事務前后數(shù)據(jù)的完整性必須保持一致。
隔離性(Isolation)多個事務并發(fā)執(zhí)行時,一個事務的執(zhí)行不應影響其他事務的執(zhí)行。
持久性(Durability)持久性是指一個事務一旦被提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫發(fā)生故障也不應該對其有任何影響。
Redis的事務總是具有ACID中的一致性和隔離性,其他特性是不支持的。當服務器運行在_AOF_持久化模式下,并且appendfsync選項的值為always時,事務也具有持久性。
二十六、Redis事務支持隔離性嗎
Redis 是單進程程序,并且它保證在執(zhí)行事務時,不會對事務進行中斷,事務可以運行直到執(zhí)行完所有事務隊列中的命令為止。因此,Redis 的事務是總是帶有隔離性的。
二十七、Redis事務保證原子性嗎,支持回滾嗎
Redis中,單條命令是原子性執(zhí)行的,但事務不保證原子性,且沒有回滾。事務中任意命令執(zhí)行失敗,其余的命令仍會被執(zhí)行。
二十八、Redis事務其他實現(xiàn)
- 基于Lua腳本,Redis可以保證腳本內(nèi)的命令一次性、按順序地執(zhí)行,其同時也不提供事務運行錯誤的回滾,執(zhí)行過程中如果部分命令運行錯誤,剩下的命令還是會繼續(xù)運行完。
- 基于中間標記變量,通過另外的標記變量來標識事務是否執(zhí)行完成,讀取數(shù)據(jù)時先讀取該標記變量判斷是否事務執(zhí)行完成。但這樣會需要額外寫代碼實現(xiàn),比較繁瑣。
二十九、集群方案-哨兵模式
哨兵的介紹sentinel,中文名是哨兵。哨兵是 redis 集群機構(gòu)中非常重要的一個組件,主要有以下功能:
- 集群監(jiān)控:負責監(jiān)控 redis master 和 slave 進程是否正常工作。
- 消息通知:如果某個 redis 實例有故障,那么哨兵負責發(fā)送消息作為報警通知給管理員。
- 故障轉(zhuǎn)移:如果 master node 掛掉了,會自動轉(zhuǎn)移到 slave node 上。
- 配置中心:如果故障轉(zhuǎn)移發(fā)生了,通知 client 客戶端新的 master 地址。
哨兵用于實現(xiàn) redis 集群的高可用,本身也是分布式的,作為一個哨兵集群去運行,互相協(xié)同工作。
故障轉(zhuǎn)移時,判斷一個 master node 是否宕機了,需要大部分的哨兵都同意才行,涉及到了分布式選舉的問題。
即使部分哨兵節(jié)點掛掉了,哨兵集群還是能正常工作的,因為如果一個作為高可用機制重要組成部分的故障轉(zhuǎn)移系統(tǒng)本身是單點的,那就很坑爹了。
哨兵的核心知識
- 哨兵至少需要 3 個實例,來保證自己的健壯性。
- 哨兵 + redis 主從的部署架構(gòu),是不保證數(shù)據(jù)零丟失的,只能保證 redis 集群的高可用性。
- 對于哨兵 + redis 主從這種復雜的部署架構(gòu),盡量在測試環(huán)境和生產(chǎn)環(huán)境,都進行充足的測試和演練。
三十、集群方案- 官方Redis Cluster 方案(服務端路由查詢)
redis 集群模式的工作原理能說一下么?在集群模式下,redis 的 key 是如何尋址的?分布式尋址都有哪些算法?了解一致性 hash 算法嗎?
簡介Redis Cluster是一種服務端Sharding技術,3.0版本開始正式提供。Redis Cluster并沒有使用一致性hash,而是采用slot(槽)的概念,一共分成16384個槽。將請求發(fā)送到任意節(jié)點,接收到請求的節(jié)點會將查詢請求發(fā)送到正確的節(jié)點上執(zhí)行。
方案說明
- 1. 通過哈希的方式,將數(shù)據(jù)分片,每個節(jié)點均分存儲一定哈希槽(哈希值)區(qū)間的數(shù)據(jù),默認分配了16384 個槽位
- 2. 每份數(shù)據(jù)分片會存儲在多個互為主從的多節(jié)點上
- 3. 數(shù)據(jù)寫入先寫主節(jié)點,再同步到從節(jié)點(支持配置為阻塞同步)
- 4. 同一分片多個節(jié)點間的數(shù)據(jù)不保持一致性
- 5. 讀取數(shù)據(jù)時,當客戶端操作的key沒有分配在該節(jié)點上時,redis會返回轉(zhuǎn)向指令,指向正確的節(jié)點
- 6. 擴容時時需要需要把舊節(jié)點的數(shù)據(jù)遷移一部分到新節(jié)點
在 redis cluster 架構(gòu)下,每個 redis 要放開兩個端口號,比如一個是 6379,另外一個就是 加1w的端口號,比如 16379。16379 端口號是用來進行節(jié)點間通信的,也就是 cluster bus 的東西,cluster bus 的通信,用來進行故障檢測、配置更新、故障轉(zhuǎn)移授權(quán)。cluster bus 用了另外一種二進制的協(xié)議,gossip 協(xié)議,用于節(jié)點間進行高效的數(shù)據(jù)交換,占用更少的網(wǎng)絡帶寬和處理時間。
節(jié)點間的內(nèi)部通信機制基本通信原理集群元數(shù)據(jù)的維護有兩種方式:集中式、Gossip 協(xié)議。redis cluster 節(jié)點間采用 gossip 協(xié)議進行通信。
- 分布式尋址算法
- hash 算法(大量緩存重建)
- 一致性 hash 算法(自動緩存遷移)+ 虛擬節(jié)點(自動負載均衡)
- redis cluster 的 hash slot 算法
優(yōu)點
- 無中心架構(gòu),支持動態(tài)擴容,對業(yè)務透明
- 具備Sentinel的監(jiān)控和自動Failover(故障轉(zhuǎn)移)能力
- 客戶端不需要連接集群所有節(jié)點,連接集群中任何一個可用節(jié)點即可
- 高性能,客戶端直連redis服務,免去了proxy代理的損耗
缺點
- 運維也很復雜,數(shù)據(jù)遷移需要人工干預
- 只能使用0號數(shù)據(jù)庫
- 不支持批量操作(pipeline管道操作)
- 分布式邏輯和存儲模塊耦合等
三十一、集群方案- 基于客戶端分配
簡介客戶端發(fā)送請求到一個代理組件,代理解析客戶端的數(shù)據(jù),并將請求轉(zhuǎn)發(fā)至正確的節(jié)點,最后將結(jié)果回復給客戶端。
特征
- 透明接入,業(yè)務程序不用關心后端Redis實例,切換成本低
- Proxy 的邏輯和存儲的邏輯是隔離的
- 代理層多了一次轉(zhuǎn)發(fā),性能有所損耗
業(yè)界開源方案
- Twtter開源的Twemproxy
- 豌豆莢開源的Codis
三十二、Redis 主從架構(gòu)
- 單機的 redis,能夠承載的 QPS 大概就在上萬到幾萬不等。對于緩存來說,一般都是用來支撐讀高并發(fā)的。因此架構(gòu)做成主從(master-slave)架構(gòu),一主多從,主負責寫,并且將數(shù)據(jù)復制到其它的slave 節(jié)點,從節(jié)點負責讀。所有的讀請求全部走從節(jié)點。這樣也可以很輕松實現(xiàn)水平擴容,支撐讀高并發(fā)。
- redis replication -> 主從架構(gòu) -> 讀寫分離 -> 水平擴容支撐讀高并發(fā)
redis replication 的核心機制
- redis 采用異步方式復制數(shù)據(jù)到 slave 節(jié)點,不過 redis2.8 開始,slave node 會周期性地確認自己每次復制的數(shù)據(jù)量;
- 一個 master node 是可以配置多個 slave node 的;
- slave node 也可以連接其他的 slave node;
- slave node 做復制的時候,不會 block master node 的正常工作;
- slave node 在做復制的時候,也不會 block 對自己的查詢操作,它會用舊的數(shù)據(jù)集來提供服務;但是復制完成的時候,需要刪除舊數(shù)據(jù)集,加載新數(shù)據(jù)集,這個時候就會暫停對外服務了;
- slave node 主要用來進行橫向擴容,做讀寫分離,擴容的 slave node 可以提高讀的吞吐量。
注意
- 如果采用了主從架構(gòu),那么建議必須開啟 master node 的持久化,不建議用 slave node 作為master node 的數(shù)據(jù)熱備,因為那樣的話,如果你關掉 master 的持久化,可能在 master 宕機重啟的時候數(shù)據(jù)是空的,然后可能一經(jīng)過復制,slave node 的數(shù)據(jù)也丟了。
- 另外,master 的各種備份方案,也需要做。萬一本地的所有文件丟失了,從備份中挑選一份 rdb去恢復 master,這樣才能確保啟動的時候,是有數(shù)據(jù)的,即使采用了后續(xù)講解的高可用機制,slave node 可以自動接管 master node,但也可能 sentinel 還沒檢測到 master failure,master node 就自動重啟了,還是可能導致上面所有的 slave node 數(shù)據(jù)被清空。
redis 主從復制的核心原理
- 當啟動一個 slave node 的時候,它會發(fā)送一個 PSYNC 命令給 master node。如果這時 slave node 初次連接到 master node,那么會觸發(fā)一次 full resynchronization 全量復制。
- 此時 master 會啟動一個后臺線程,開始生成一份 RDB 快照文件,同時還會將從客戶端 client 新收到的所有寫命令緩存在內(nèi)存中。RDB 文件生成完畢后, master會將這個 RDB 發(fā)送給 slave,slave 會先寫入本地磁盤,然后再從本地磁盤加載到內(nèi)存中,接著 master 會將內(nèi)存中緩存的寫命令發(fā)送到 slave,slave 也會同步這些數(shù)據(jù)。
- slave node 如果跟 master node 有網(wǎng)絡故障,斷開了連接,會自動重連,連接之后 master node僅會復制給 slave 部分缺少的數(shù)據(jù)。
過程原理
- 1. 當從庫和主庫建立MS關系后,會向主數(shù)據(jù)庫發(fā)送 SYNC 命令
- 2. 主庫接收到 SYNC 命令后會開始在后臺保存快照(RDB持久化過程),并將期間接收到的寫命令緩存起來
- 3. 當快照完成后,主Redis會將快照文件和所有緩存的寫命令發(fā)送給從Redis
- 4. 從Redis接收到后,會載入快照文件并且執(zhí)行收到的緩存的命令
- 5. 之后,主Redis每當接收到寫命令時就會將命令發(fā)送從Redis,從而保證數(shù)據(jù)的一致
缺點
所有的slave節(jié)點數(shù)據(jù)的復制和同步都由master節(jié)點來處理,會造成 master 節(jié)點壓力太大,使用主從從結(jié)構(gòu)來解決。
三十三、Redis集群的主從復制模型是怎樣的?
為了使在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用,所以集群使用了主從復制模型,每個節(jié)點都會有N-1個復制品。
三十四、生產(chǎn)環(huán)境中的 redis 是怎么部署的?
redis cluster,10 臺機器,5 臺機器部署了 redis 主實例,另外 5 臺機器部署了 redis 的從實例,每個主實例掛了一個從實例,5 個節(jié)點對外提供讀寫服務,每個節(jié)點的讀寫高峰qps可能可以達到每秒 5 萬,5 臺機器最多是 25 萬讀寫請求/s。
機器是什么配置?
- 32G 內(nèi)存+ 8 核 CPU + 1T 磁盤,但是分配給 redis 進程的是10g內(nèi)存,一般線上生產(chǎn)環(huán)境,redis 的內(nèi)存盡量不要超過 10g,超過 10g 可能會有問題。
- 5 臺機器對外提供讀寫,一共有 50g 內(nèi)存。因為每個主實例都掛了一個從實例,所以是高可用的,任何一個主實例宕機,都會自動故障遷移,redis 從實例會自動變成主實例繼續(xù)提供讀寫服務。
你往內(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 左右的請求量。
三十五、說說Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽,集群的每個節(jié)點負責一部分hash槽。
三十六、Redis集群會有寫操作丟失嗎?為什么?
Redis并不能保證數(shù)據(jù)的強一致性,這意味著在實際中集群在特定的條件下可能會丟失寫操作。
三十七、Redis集群之間是如何復制的?
異步復制
三十八、Redis集群最大節(jié)點個數(shù)是多少?
16384個
三十九、Redis集群如何選擇數(shù)據(jù)庫?
Redis集群目前無法做數(shù)據(jù)庫選擇,默認在0數(shù)據(jù)庫。
四十、Redis是單線程的,如何提高多核CPU的利用率?
可以在同一個服務器部署多個Redis的實例,并把他們當作不同的服務器來使用,在某些時候,無論如何一個服務器是不夠的, 所以,如果你想使用多個CPU,你可以考慮一下分片(shard)。
四十一、為什么要做Redis分區(qū)?
分區(qū)可以讓Redis管理更大的內(nèi)存,Redis將可以使用所有機器的內(nèi)存。如果沒有分區(qū),你最多只能使用一臺機器的內(nèi)存。分區(qū)使Redis的計算能力通過簡單地增加計算機得到成倍提升,Redis的網(wǎng)絡帶寬也會隨著計算機和網(wǎng)卡的增加而成倍增長。
四十二、你知道有哪些Redis分區(qū)實現(xiàn)方案?
- 客戶端分區(qū)就是在客戶端就已經(jīng)決定數(shù)據(jù)會被存儲到哪個redis節(jié)點或者從哪個redis節(jié)點讀取。大多數(shù)客戶端已經(jīng)實現(xiàn)了客戶端分區(qū)。
- 代理分區(qū)意味著客戶端將請求發(fā)送給代理,然后代理決定去哪個節(jié)點寫數(shù)據(jù)或者讀數(shù)據(jù)。代理根據(jù)分區(qū)規(guī)則決定請求哪些Redis實例,然后根據(jù)Redis的響應結(jié)果返回給客戶端。
- redis和memcached的一種代理實現(xiàn)就是Twemproxy查詢路由(Query routing) 的意思是客戶端隨機地請求任意一個redis實例,然后由Redis將請求轉(zhuǎn)發(fā)給正確的Redis節(jié)點。Redis Cluster實現(xiàn)了一種混合形式的查詢路由,但并不是直接將請求從一個redis節(jié)點轉(zhuǎn)發(fā)到另一個redis節(jié)點,而是在客戶端的幫助下直接redirected到正確的redis節(jié)點。
四十三、Redis分區(qū)有什么缺點?
- 涉及多個key的操作通常不會被支持。例如你不能對兩個集合求交集,因為他們可能被存儲到不同的Redis實例(實際上這種情況也有辦法,但是不能直接使用交集指令)。
- 同時操作多個key,則不能使用Redis事務
- 分區(qū)使用的粒度是key,不能使用一個非常長的排序key存儲一個數(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)
- 當使用分區(qū)的時候,數(shù)據(jù)處理會非常復雜,例如為了備份你必須從不同的Redis實例和主機同時收集RDB / AOF文件。
- 分區(qū)時動態(tài)擴容或縮容可能非常復雜。Redis集群在運行時增加或者刪除Redis節(jié)點,能做到最大程度對用戶透明地數(shù)據(jù)再平衡,但其他一些客戶端分區(qū)或者代理分區(qū)方法則不支持這種特性。然而,有一種預分片的技術也可以較好的解決這個問題。
四十四、Redis實現(xiàn)分布式鎖
- Redis為單進程單線程模式,采用隊列模式將并發(fā)訪問變成串行訪問,且多客戶端對Redis的連接并不存在競爭關系,Redis中可以使用 setNx 命令實現(xiàn)分布式鎖。
- 當且僅當 key 不存在,將 key 的值設為 value。 若給定的 key 已經(jīng)存在,則 setNx 不做任何動作
- SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡寫。
- 返回值:設置成功,返回 1 。設置失敗,返回 0。
- 使用setNx完成同步鎖的流程及事項如下:
- 使用SETNX命令獲取鎖,若返回0(key已存在,鎖已存在)則獲取失敗,反之獲取成功
- 為了防止獲取鎖后程序出現(xiàn)異常,導致其他線程/進程調(diào)用setNx命令總是返回0而進入死鎖狀態(tài),需要為該key設置一個“合理”的過期時間釋放鎖,使用DEL命令將鎖數(shù)據(jù)刪除。
四十五、如何解決 Redis 的并發(fā)競爭 Key 問題
- 所謂 Redis 的并發(fā)競爭 Key 的問題也就是多個系統(tǒng)同時對一個 key 進行操作,但是最后執(zhí)行的順序和我們期望的順序不同,這樣也就導致了結(jié)果的不同!
- 推薦一種方案:分布式鎖(zookeeper 和 redis 都可以實現(xiàn)分布式鎖)。(如果不存在 Redis 的并發(fā)競爭 Key 問題,不要使用分布式鎖,這樣會影響性能)
- 基于zookeeper臨時有序節(jié)點可以實現(xiàn)的分布式鎖。大致思想為:每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應的指定節(jié)點的目錄下,生成一個唯一的瞬時有序節(jié)點。判斷是否獲取鎖的方式很簡單,只需要判斷有序節(jié)點中序號最小的一個。 當釋放鎖的時候,只需將這個瞬時節(jié)點刪除即可。同時,其可以避免服務宕機導致的鎖無法釋放,而產(chǎn)生的死鎖問題。完成業(yè)務流程后,刪除對應的子節(jié)點釋放鎖。
- 在實踐中,當然是從以可靠性為主。所以首推Zookeeper。
四十六、分布式Redis是前期做還是后期規(guī)模上來了再做好?為什么?
- 既然Redis是如此的輕量(單實例只使用1M內(nèi)存),為防止以后的擴容,最好的辦法就是一開始就啟動較多實例。即便你只有一臺服務器,你也可以一開始就讓Redis以分布式的方式運行,使用分區(qū),在同一臺服務器上啟動多個實例。
- 一開始就多設置幾個Redis實例,例如32或者64個實例,對大多數(shù)用戶來說這操作起來可能比較麻煩,但是從長久來看做這點犧牲是值得的。這樣的話,當你的數(shù)據(jù)不斷增長,需要更多的Redis服務器時,你需要做的就是僅僅將Redis實例從一臺服務遷移到另外一臺服務器而已(而不用考慮重新分區(qū)的問題)。
- 一旦你添加了另一臺服務器,你需要將你一半的Redis實例從第一臺機器遷移到第二臺機器。
四十七、什么是 RedLock
Redis 官方站提出了一種權(quán)威的基于 Redis 實現(xiàn)分布式鎖的方式名叫 Redlock,此種方式比原先的單節(jié)點的方法更安全。它可以保證以下特性:
- 1. 安全特性:互斥訪問,即永遠只有一個 client 能拿到鎖
- 2. 避免死鎖:最終 client 都可能拿到鎖,不會出現(xiàn)死鎖的情況,即使原本鎖住某資源的 client crash 了或者出現(xiàn)了網(wǎng)絡分區(qū)
- 3. 容錯性:只要大部分 Redis 節(jié)點存活就可以正常提供服務
四十八、什么是redis穿透?
就是用戶請求透過redis去請求mysql服務器,導致mysql壓力過載。但一個web服務里,極容易出現(xiàn)瓶頸的就是mysql,所以才讓redis去分擔mysql 的壓力,所以這種問題是萬萬要避免的。
解決方法:
- 1. 從緩存取不到的數(shù)據(jù),在數(shù)據(jù)庫中也沒有取到,這時也可以將key-value對寫為key-null,緩存有效時間可以設置短點,如30秒(設置太長會導致正常情況也沒法使用)。這樣可以防止攻擊用戶反復用同一個id暴力攻擊。
- 2. 接口層增加校驗,如用戶鑒權(quán)校驗,id做基礎校驗,id<=0的直接攔截。
- 3. 采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的 bitmap 中,一個一定不存在的數(shù)據(jù)會被這個 bitmap 攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力。
四十九、什么是redis雪崩?
就是redis服務由于負載過大而宕機,導致mysql的負載過大也宕機,最終整個系統(tǒng)癱瘓。
解決方法:
- 1. redis集群,將原來一個人干的工作,分發(fā)給多個人干
- 2. 緩存預熱(關閉外網(wǎng)訪問,先開啟mysql,通過預熱腳本將熱點數(shù)據(jù)寫入緩存中,啟動緩存。開啟外網(wǎng)服務)
- 3. 數(shù)據(jù)不要設置相同的生存時間,不然過期時,redis壓力會大
五十、什么是redis擊穿?
高并發(fā)下,由于一個key失效,而導致多個線程去mysql查同一業(yè)務數(shù)據(jù)并存到redis(并發(fā)下,存了多份數(shù)據(jù)),而一段時間后,多份數(shù)據(jù)同時失效。導致壓力驟增
解決方法:
- 1. 分級緩存(緩存兩份數(shù)據(jù),第二份數(shù)據(jù)生存時間長一點作為備份,第一份數(shù)據(jù)用于被請求命中,如果第二份數(shù)據(jù)被命中說明第一份數(shù)據(jù)已經(jīng)過期,要去mysql請求數(shù)據(jù)重新緩存兩份數(shù)據(jù))
- 2. 計劃任務(假如數(shù)據(jù)生存時間為30分鐘,計劃任務就20分鐘執(zhí)行一次更新緩存數(shù)據(jù))
五十一、緩存預熱
緩存預熱就是系統(tǒng)上線后,將相關的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣就可以避免在用戶請求的時候,先查詢數(shù)據(jù)庫,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預熱的緩存數(shù)據(jù)!
解決方案
- 1. 直接寫個緩存刷新頁面,上線時手工操作一下;
- 2. 數(shù)據(jù)量不大,可以在項目啟動的時候自動進行加載;
- 3. 定時刷新緩存;
五十二、緩存降級
當訪問量劇增、服務出現(xiàn)問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務。系統(tǒng)可以根據(jù)一些關鍵數(shù)據(jù)進行自動降級,也可以配置開關實現(xiàn)人工降級。緩存降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的(如加入購物車、結(jié)算)。在進行降級之前要對系統(tǒng)進行梳理,看看系統(tǒng)是不是可以丟卒保帥;從而梳理出哪些必須誓死保護,哪些可降級;比如可以參考日志級別設置預案:
- 1. 一般:比如有些服務偶爾因為網(wǎng)絡抖動或者服務正在上線而超時,可以自動降級;
- 2. 警告:有些服務在一段時間內(nèi)成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發(fā)送告警;
- 3. 錯誤:比如可用率低于90%,或者數(shù)據(jù)庫連接池被打爆了,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值,此時可以根據(jù)情況自動降級或者人工降級;
- 4. 嚴重錯誤:比如因為特殊原因數(shù)據(jù)錯誤了,此時需要緊急人工降級。
服務降級的目的,是為了防止Redis服務故障,導致數(shù)據(jù)庫跟著一起發(fā)生雪崩問題。因此,對于不重要的緩存數(shù)據(jù),可以采取服務降級策略,例如一個比較常見的做法就是,Redis出現(xiàn)問題,不去數(shù)據(jù)庫查詢,而是直接返回默認值給用戶。
五十三、熱點數(shù)據(jù)和冷數(shù)據(jù)
- 熱點數(shù)據(jù),緩存才有價值。
- 對于冷數(shù)據(jù)而言,大部分數(shù)據(jù)可能還沒有再次訪問到就已經(jīng)被擠出內(nèi)存,不僅占用內(nèi)存,而且價值不大。頻繁修改的數(shù)據(jù),看情況考慮使用緩存。
- 對于熱點數(shù)據(jù),比如我們的某IM產(chǎn)品,生日祝福模塊,當天的壽星列表,緩存以后可能讀取數(shù)十萬次。再舉個例子,某導航產(chǎn)品,我們將導航信息,緩存以后可能讀取數(shù)百萬次。
- 數(shù)據(jù)更新前至少讀取兩次,緩存才有意義。這個是最基本的策略,如果緩存還沒有起作用就失效了,那就沒有太大價值了。
- 那存不存在,修改頻率很高,但是又不得不考慮緩存的場景呢?有!比如,這個讀取接口對數(shù)據(jù)庫的壓力很大,但是又是熱點數(shù)據(jù),這個時候就需要考慮通過緩存手段,減少數(shù)據(jù)庫的壓力,比如我們的某助手產(chǎn)品的,點贊數(shù),收藏數(shù),分享數(shù)等是非常典型的熱點數(shù)據(jù),但是又不斷變化,此時就需要將數(shù)據(jù)同步保存到Redis緩存,減少數(shù)據(jù)庫壓力。
五十四、緩存熱點key
緩存中的一個Key(比如一個促銷商品),在某個時間點過期的時候,恰好在這個時間點對這個Key有大量的并發(fā)請求過來,這些請求發(fā)現(xiàn)緩存過期一般都會從后端DB加載數(shù)據(jù)并回設到緩存,這個時候大并發(fā)的請求可能會瞬間把后端DB壓垮。
解決方案對緩存查詢加鎖,如果KEY不存在,就加鎖,然后查DB入緩存,然后解鎖;其他進程如果發(fā)現(xiàn)有鎖就等待,然后等解鎖后返回數(shù)據(jù)或者進入DB查詢。
五十五、Redis支持的Java客戶端都有哪些?官方推薦用哪個?
Redisson、Jedis、lettuce等等,官方推薦使用Redisson。
五十六、Redis和Redisson有什么關系?
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相比,功能較為簡單,不支持字符串操作,不支持排序、事務、管道、分區(qū)等Redis特性。
- Redisson的宗旨是促進使用者對Redis的關注分離,從而讓使用者能夠?qū)⒕Ω械胤旁谔幚順I(yè)務邏輯上。
五十八、Redis與Memcached的區(qū)別
兩者都是非關系型內(nèi)存鍵值數(shù)據(jù)庫,現(xiàn)在公司一般都是用 Redis 來實現(xiàn)緩存,而且 Redis 自身也越來越強大了!Redis 與 Memcached 主要有以下不同:
- 1. memcached所有的值均是簡單的字符串,redis作為其替代者,支持更為豐富的數(shù)據(jù)類型
- 2. redis的速度比memcached快很多
- 3. redis可以持久化其數(shù)據(jù)
五十九、如何保證緩存與數(shù)據(jù)庫雙寫時的數(shù)據(jù)一致性?
- 你只要用緩存,就可能會涉及到緩存與數(shù)據(jù)庫雙存儲雙寫,你只要是雙寫,就一定會有數(shù)據(jù)一致性的問題,那么你如何解決一致性問題?
- 一般來說,就是如果你的系統(tǒng)不是嚴格要求 緩存+數(shù)據(jù)庫 必須一致性的話,緩存可以稍微的跟數(shù)據(jù)庫偶爾有不一致的情況,最好不要做這個方案,
- 讀請求和寫請求串行化,串到一個內(nèi)存隊列里去,這樣就可以保證一定不會出現(xiàn)不一致的情況。串行化之后,就會導致系統(tǒng)的吞吐量會大幅度的降低,用比正常情況下多幾倍的機器去支撐線上的一個請求。
- 還有一種方式就是可能會暫時產(chǎn)生不一致的情況,但是發(fā)生的幾率特別小,就是先更新數(shù)據(jù)庫,然后再刪除緩存。
問題場景1:先寫緩存,再寫數(shù)據(jù)庫,緩存寫成功,數(shù)據(jù)庫寫失敗
描述:
緩存寫成功,但寫數(shù)據(jù)庫失敗或者響應延遲,則下次讀取(并發(fā)讀)緩存時,就出現(xiàn)臟讀
解決:
這個寫緩存的方式,本身就是錯誤的,需要改為先寫數(shù)據(jù)庫,把舊緩存置為失效;讀取數(shù)據(jù)的時候,如果緩存不存在,則讀取數(shù)據(jù)庫再寫緩存
問題場景2:先寫數(shù)據(jù)庫,再寫緩存,數(shù)據(jù)庫寫成功,緩存寫失敗
描述:
寫數(shù)據(jù)庫成功,但寫緩存失敗,則下次讀取(并發(fā)讀)緩存時,則讀不到數(shù)據(jù)
解決:
緩存使用時,假如讀緩存失敗,先讀數(shù)據(jù)庫,再回寫緩存的方式實現(xiàn)
問題場景3:需要緩存異步刷新
描述:
指數(shù)據(jù)庫操作和寫緩存不在一個操作步驟中,比如在分布式場景下,無法做到同時寫緩存或需要異步刷新(補救措施)時候
解決:
確定哪些數(shù)據(jù)適合此類場景,根據(jù)經(jīng)驗值確定合理的數(shù)據(jù)不一致時間,用戶數(shù)據(jù)刷新的時間間隔
六十、Redis常見性能問題和解決方案?
- 1. Master最好不要做任何持久化工作,包括內(nèi)存快照和AOF日志文件,特別是不要啟用內(nèi)存快照做持久化。
- 2. 如果數(shù)據(jù)比較關鍵,某個Slave開啟AOF備份數(shù)據(jù),策略為每秒同步一次。
- 3. 為了主從復制的速度和連接的穩(wěn)定性,Slave和Master最好在同一個局域網(wǎng)內(nèi)。
- 4. 盡量避免在壓力較大的主庫上增加從庫
- 5. Master調(diào)用BGRE WRITE AOF重寫AOF文件,AOF在重寫的時候會占大量的CPU和內(nèi)存資源,導致服務load過高,出現(xiàn)短暫服務暫停現(xiàn)象。
- 6. 為了Master的穩(wěn)定性,主從復制不要用圖狀結(jié)構(gòu),用單向鏈表結(jié)構(gòu)更穩(wěn)定,即主從關系為:
- Master<–Slave1<–Slave2<–Slave3…,這樣的結(jié)構(gòu)也方便解決單點故障問題,實現(xiàn)Slave對Master的替換,也即,如果Master掛了,可以立馬啟用Slave1做Master,其他不變。
六十一、Redis官方為什么不提供Windows版本?
因為目前Linux版本已經(jīng)相當穩(wěn)定,而且用戶量很大,無需開發(fā)windows版本,反而會帶來兼容性等問題。
六十二、一個字符串類型的值能存儲最大容量是多少?
512M
六十三、Redis如何做大量數(shù)據(jù)插入?
Redis2.6開始redis-cli支持一種新的被稱之為pipe mode的新模式用于執(zhí)行大量數(shù)據(jù)插入工作。
六十四、假如Redis里面有1億個key,其中有10w個key是以某個固定的已知的前綴開頭的,如果將它們?nèi)空页鰜恚?/span>
- 使用keys指令可以掃出指定模式的key列表。
- 對方接著追問:如果這個redis正在給線上的業(yè)務提供服務,那使用keys指令會有什么問題?
- 這個時候你要回答redis關鍵的一個特性:redis的單線程的。keys指令會導致線程阻塞一段時間,線上服務會停頓,直到指令執(zhí)行完畢,服務才能恢復。這個時候可以使用scan指令,scan指令可以無阻塞的提取出指定模式的key列表,但是會有一定的重復概率,在客戶端做一次去重就可以了,但是整體所花費的時間會比直接用keys指令長。
六十五、Redis如何實現(xiàn)延時隊列
使用sorted set,使用時間戳做score, 消息內(nèi)容作為key,調(diào)用zadd來生產(chǎn)消息,消費者使用zrang by score獲取n秒之前的數(shù)據(jù)做輪詢處理。
六十六、Redis回收進程如何工作的?
- 1. 一個客戶端運行了新的命令,添加了新的數(shù)據(jù)。
- 2. Redis檢查內(nèi)存使用情況,如果大于maxmemory的限制,則根據(jù)設定好的策略進行回收。
- 3. 一個新的命令被執(zhí)行,等等。
- 4. 所以我們不斷地穿越內(nèi)存限制的邊界,通過不斷達到邊界然后不斷地回收回到邊界以下。如果一個命令的結(jié)果導致大量內(nèi)存被使用(例如很大的集合的交集保存到一個新的鍵),不用多久內(nèi)存限制就會被這個內(nèi)存使用量超越。
六十七、Redis回收使用的是什么算法?
LRU算法
落葉他鄉(xiāng)樹
網(wǎng)站標題:Redis 常見問題
網(wǎng)頁地址:http://www.chinadenli.net/article32/dsdihpc.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、全網(wǎng)營銷推廣、網(wǎng)站設計、動態(tài)網(wǎng)站、網(wǎng)站導航、響應式網(wǎng)站
廣告
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源:
創(chuàng)新互聯(lián)