優質博文:IT-BLOG-CN
一、Redis 為什么那么快
【1】完全基于內存,絕大部分請求是純粹的內存操作,非常快速。數據存在內存中。
【2】數據結構簡單,對數據操作也簡單,Redis中的數據結構是專門進行設計的。
【3】采用單線程,避免不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗。
【4】使用多路IO復用模型,非阻塞IO。利用epoll可以同時監察多個流的 IO事件的能力,在空閑的時候,會把當前線程阻塞掉,當有一個或多個流有 IO事件時,就從阻塞態中喚醒,epoll就輪詢哪些真正發生了事件的流,并且只依次順序的處理就緒的流,這種做法就避免了大量的無用操作。多路指的是多個網絡連接,“復用”指的是復用同一個線程。
二、Redis 與 Memcached 的區別
Redis 與 Memcached 的相似之處:
【1】Redis 和 Memcached 都是內存數據存儲系統,都用作內存中的鍵值數據存儲;
【2】Redis 和 Memcached 都屬于NoSQL系列數據管理解決方案,兩者都基于鍵值數據模型;
【3】Redis 和 Memcached 都將所有數據保存在 RAM 中,這當然使它們作為緩存層非常有用;
Redis 與 Memcached 的區別:
【1】Redis 和 Memcached都是將數據存放在內存中,都是內存數據庫。不過Memcached 還可用于緩存其他東西,例如圖片、視頻等等;
【2】Redis 不僅僅支持簡單的 k/v 類型的數據,同時還提供 list,set,zset,hash等數據結構的存儲;
【3】虛擬內存 Redis 當物理內存用完時,可以將一些很久沒用到的 value 交換到磁盤;
【4】過期策略 Memcached 在 set 時就指定,例如:set key1 0 0,即永不過期。Redis 可以通過例如 expire 設定,例如:expire name 10;
【5】存儲數據安全性 Memcached 掛掉后,數據就沒了。Redis可以定期保存到磁盤(持久化);
【6】災難恢復 Memcached 掛掉后,數據不可恢復。Redis 數據丟失后可以通過 rdb 或 aof恢復;
【7】Memcached不支持復制,Redis支持主從復制,允許從屬 Redis服務器成為主服務器的精確副本;來自任何 Redis服務器的數據都可以復制到任意數量的從屬服務器;
【8】應用場景不一樣:Redis 除了作為 NoSQL數據庫使用外,還能用做消息隊列、數據堆棧和數據緩存等;Memcached適合于緩存SQL語句、數據集、用戶臨時性數據、延遲查詢數據和 session等;
【9】Memcached 的讀寫速度高于 Redis,因為Redis 是單線程的,而 Memcached 是多線程的;
【10】Memcached 單個 key-value大小有限,一個 value最大只支持1MB,而 Redis最大支持512MB;
三、Redis 有哪幾種數據淘汰策略
Redis 檢查內存使用情況,如果已使用的內存大于 maxmemory的值則開始根據用戶配置的不同淘汰策略來淘汰內存(key),從而換取一定的內存。maxmemory=0 的時候表示我們對 Redis的內存使用沒有限制。淘汰策略如下:
【1】noeviction: 返回錯誤。當內存使用達到閾值的時候,所有引起申請內存的命令會報錯。
【2】allkeys-lru: 在主鍵空間中,優先移除最近未使用的key。
【3】volatile-lru: 在設置了過期時間的鍵空間中,優先移除最近未使用的key。
【4】allkeys-random: 回收隨機的鍵使得新添加的數據有空間存放。
【5】volatile-random: 回收隨機的鍵使得新添加的數據有空間存放,但僅限于在過期集合的鍵。
【6】volatile-ttl: 回收在過期集合的鍵,并且優先回收存活時間(TTL)較短的鍵,使得新添加的數據有空間存放。
四、Redis 支持哪幾種數據類型
Reids 支持7中數據結構,最常用的是 String、List、Set、Sorted Set、Hash 其內部結構及使用參照博客鏈接;
五、Redis 集群方案什么情況下會導致整個集群不可用
假如有A,B,C三個節點的集群,在沒有主從復制模型的情況下,其中一個節點掛掉,那么整個集群就會缺少某個范圍的槽而不可用。所以從節點很重要。
六、Redis 哈希槽的概念
Redis 集群沒有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384個哈希槽,每個 key通過 CRC16校驗后對16384 取模來決定放置哪個槽,集群的每個節點負責一部分 hash槽。
七、Redis 集群會有寫操作丟失嗎
Redis 并不能保證數據的強一致性,這意味這在實際生產中集群在特定的條件下可能會丟失寫操作。
八、Redis 集群之間是如何復制的
【博客連接】:優質鏈接
九、Redis 集群如何選擇數據庫
Redis 集群目前無法做數據庫選擇,默認在0數據庫。
十、Redis 中的管道(Pipeline)有什么用
客戶端將請求傳送給服務器,服務器處理完畢后,再將響應回復給客戶端。這要花費一個網絡數據包來回的時間。如果連續執行多條指令,那么就會花費多個網絡數據包來回的時間(多條指令,一條一條發送給服務器)。
管道的本質是: 將多個連續的讀寫操作合并后總共花費一次網絡來回。就好像連續的寫操作合并了,連續的讀操作也合并了一樣。服務器根本沒有任何區別對待,還是走著收著一條消息、執行一條消息、回復一條消息的正常流程。Redis 自帶了管道的壓力測試工具 redis-benchmark,使用此工具可以進行管道測試:
redis-benchmark -t set -q
SET: 54938.05 requests per second# -P 表示管道內并行的請求數量。 當P=2 時,QPS 達到 9W/s
# 當P達到一定值時,會下降,因為單線程CPU消耗已經達到 100%,所以無法上升
redis-benchmark -t set -P 2 -q
SET: 93238.15 requests per second
將多個命令發送到服務器,而不用等待回復,最后在一個步驟中讀取該答復。這就是管道(pipelining),是一種幾十年來廣泛使用的技術。例如許多 POP3協議已經實現支持這個功能,大大加快了從服務器下載新郵件的過程。
十一、怎么理解 Redis事務
事務是一個單獨的隔離操作: 事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。事務是一個原子操作:事務中的命令要么全部被執行,要么全部都不執行。但是如果某個事務執行失敗,也不會進行回滾的。
十二、Redis key 的過期時間和永久有效分別怎么設置
EXPIRE 和 PERSIST命令。
十三、Redis 如何做內存優化
盡可能使用散列表(hashes),散列表(是說散列表里面存儲的數少)使用的內存非常小,所以你應該盡可能的將你的數據模型抽象到一個散列表里面。比如你的 web系統中有一個用戶對象,不要為這個用戶的名稱,姓氏,郵箱,密碼設置單獨的key,而是應該把這個用戶的所有信息存儲到一張散列表里面。
十四、Redis 回收進程如何工作的
【1】一個客戶端運行了新的命令,添加了新的數據。
【2】Redis 檢查內存使用情況,如果大于 maxmemory的限制, 則根據設定好的策略進行回收。
【3】一個新的命令被執行,等等。
【4】所以我們不斷地穿越內存限制的邊界,通過不斷達到邊界然后不斷地回收回到邊界以下。
如果一個命令的結果導致大量內存被使用(例如很大的集合的交集保存到一個新的鍵),不用多久內存限制就會被這個內存使用量超越。
十五、Redis 回收使用的是什么算法
Redis 中采用兩種算法進行內存回收,引用計數算法以及LRU算法(最近最久未使用算法)。
十六、Redis 如何做大量數據插入
Redis2.6 開始 redis-cli 支持一種新的被稱之為 pipe mode 的新模式用于執行大量數據插入工作。
十七、為什么要做 Redis分區
分區可以讓 Redis管理更大的內存,Redis 將可以使用所有機器的內存。如果沒有分區,你最多只能使用一臺機器的內存。分區使 Redis的計算能力通過簡單地增加計算機得到成倍提升,Redis 的網絡帶寬也會隨著計算機和網卡的增加而成倍增長。
十八、你知道有哪些 Redis分區實現方案
【1】客戶端分區: 就是在客戶端就已經決定數據會被存儲到哪個 Redis節點或者從哪個 Redis節點讀取。大多數客戶端已經實現了客戶端分區。
【2】代理分區: 意味著客戶端將請求發送給代理,然后代理決定去哪個節點寫數據或者讀數據。代理根據分區規則決定請求哪些 Redis實例,然后根據 Redis的響應結果返回給客戶端。Redis 和 memcached 的一種代理實現就是 Twemproxy。
【3】查詢路由(Query routing) : 意思是客戶端隨機地請求任意一個 Redis實例,然后由 Redis將請求轉發給正確的 Redis節點。Redis Cluster 實現了一種混合形式的查詢路由,但并不是直接將請求從一個 Redis節點轉發到另一個 Redis節點,而是在客戶端的幫助下直接 Redirected到正確的 Redis節點。
十九、Redis 持久化數據和緩存怎么做擴容
【1】如果 Redis被當做緩存使用,使用一致性哈希實現動態擴容縮容。
【2】如果 Redis被當做一個持久化存儲使用,必須使用固定的 keys-to-nodes 映射關系,節點的數量一旦確定不能變化。否則的話(即 Redis節點需要動態變化的情況),必須使用可以在運行時進行數據再平衡的一套系統,而當前只有Redis集群可以做到這樣。
二十、分布式 Redis是前期做還是后期規模上來了再做好?為什么?
既然 Redis是如此的輕量(單實例只使用1M內存),為防止以后的擴容,最好的辦法就是一開始就啟動較多實例。即便你只有一臺服務器,你也可以一開始就讓 Redis以分布式的方式運行,使用分區,在同一臺服務器上啟動多個實例。
一開始就多設置幾個Redis實例,例如 32或者 64個實例,對大多數用戶來說這操作起來可能比較麻煩,但是從長久來看做這點犧牲是值得的。
這樣的話,當你的數據不斷增長,需要更多的 Redis服務器時,你需要做的就是僅僅將 Redis實例從一臺服務遷移到另外一臺服務器而已(而不用考慮重新分區的問題)。一旦你添加了另一臺服務器,你需要將你一半的 Redis實例從第一臺機器遷移到第二臺機器。
二十一、Twemproxy 是什么
Twemproxy 是 Twitter 維護的(緩存)代理系統,代理 Memcached 的 ASCII協議和 Redis協議。它是單線程程序,使用C語言編寫,運行起來非常快。它是采用 Apache 2.0 license的開源軟件。 Twemproxy 支持自動分區,如果其代理的其中一個 Redis節點不可用時,會自動將該節點排除(這將改變原來的 keys-instances的映射關系,所以你應該僅在把 Redis當緩存時使用Twemproxy)。 Twemproxy 本身不存在單點問題,因為你可以啟動多個 Twemproxy實例,然后讓你的客戶端去連接任意一個Twemproxy 實例。 Twemproxy 是 Redis客戶端和服務器端的一個中間層,由它來處理分區功能應該不算復雜,并且應該算比較可靠的。
二十二、Redis 與其他 key-value存儲有什么不同
【1】Redis 有著更為復雜的數據結構并且提供對他們的原子性操作,這是一個不同于其他數據庫的進化路徑。Redis 的數據類型都是基于基本數據結構的同時對程序員透明,無需進行額外的抽象。
【2】Redis 運行在內存中但是可以持久化到磁盤,所以在對不同數據集進行高速讀寫時需要權衡內存,應為數據量不能大于硬件內存。在內存數據庫方面的另一個優點是, 相比在磁盤上相同的復雜的數據結構,在內存中操作起來非常簡單,這樣Redis可以做很多內部復雜性很強的事情。 同時,在磁盤格式方面他們是緊湊的以追加的方式產生的,因為他們并不需要進行隨機訪問。
二十三、Redis 的內存占用情況怎么樣
舉個例子: 100萬個鍵值對(鍵是0到999999值是字符串“hello world”)在我的 32位的Mac筆記本上用了100MB。同樣的數據放到一個 key里只需要16MB, 這是因為鍵值有一個很大的開銷。 在 Memcached上執行也是類似的結果,但是相對 Redis的開銷要小一點點,因為 Redis會記錄類型信息引用計數等等。當然,大鍵值對時兩者的比例要好很多。64位的系統比32位的需要更多的內存開銷,尤其是鍵值對都較小時,這是因為 64位的系統里指針占用了8個字節。 但是,當然,64位系統支持更大的內存,所以為了運行大型的 Redis服務器或多或少的需要使用 64位的系統。
二十四、哪些辦法可以降低 Redis的內存使用情況
如果你使用的是 32位的 Redis實例,可以好好利用 Hash、list、sorted set、set等集合類型數據,因為通常情況下很多小的 Key-Value 可以用更緊湊的方式存放到一起。
二十五、查看 Redis使用情況及狀態信息用什么命令
Redis 可以使用以下命令查看使用情況及狀態信息:
【1】INFO 命令: 該命令可以查看 Redis 的各項統計信息,包括內存使用情況、連接數、命中率等等。
具體使用步驟:
1、在 Redis 客戶端中輸入 INFO 命令。
2、程序會返回一份詳細的統計信息,包括服務器的基本信息、客戶端信息、內存信息、持久化信息等等。
127.0.0.1:6379> INFO
【2】MONITOR 命令: 該命令可以監視 Redis 服務器正在處理的命令,并以實時日志的形式輸出。
具體使用步驟:
1、在 Redis 客戶端中輸入 MONITOR 命令。
2、程序會開始輸出 Redis 服務器正在處理的命令及其執行結果。
127.0.0.1:6379> MONITOR
【3】CLIENT LIST 命令: 該命令可以查看當前連接到 Redis 服務器的客戶端信息。
具體使用步驟:
1、在 Redis 客戶端中輸入 CLIENT LIST 命令。
2、程序會返回連接到Redis服務器的所有客戶端的詳細信息,包括客戶端 IP 地址、端口號、連接時間等等。
127.0.0.1:6379> CLIENT LIST
【4】DBSIZE 命令: 該命令可以查看當前 Redis 數據庫中的鍵值對數量。
具體使用步驟:
1、在 Redis 客戶端中輸入 DBSIZE 命令。
2、程序會返回當前數據庫中鍵值對的數量。
127.0.0.1:6379> DBSIZE
二十六、Redis 的內存用完了會發生什么
如果達到設置的上限,Redis 的寫命令會返回錯誤信息(但是讀命令還可以正常返回。)或者你可以將 Redis當緩存來使用配置淘汰機制,當 Redis達到內存上限時會沖刷掉舊的內容。
二十七、Redis 是單線程的,如何提高多核CPU的利用率
可以在同一個服務器部署多個 Redis的實例,并把他們當作不同的服務器來使用,在某些時候,無論如何一個服務器是不夠的, 所以,如果你想使用多個 CPU,你可以考慮一下分片(shard)。
二十八、一個 Redis實例最多能存放多少的keys?List、Set、Sorted Set他們最多能存放多少元素
【1】理論上 Redis可以處理多達 232的 keys,并且在實際中進行了測試,每個實例至少存放了 2億5千萬的 keys。我們正在測試一些較大的值。
【2】任何 list、set、和 sorted set都可以放 232個元素。換句話說,Redis 的存儲極限是系統中的可用內存值。
二十九、Redis 常見性能問題和解決方案
【1】Master 最好不要做任何持久化工作,如 RDB內存快照和 AOF日志文件;
【2】如果數據比較重要,某個 Slave 開啟 AOF備份數據,策略設置為每秒同步一次;
【3】為了主從復制的速度和連接的穩定性,Master 和 Slave最好在同一個局域網內;
【4】盡量避免在壓力很大的主庫上增加從庫;
【5】主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即:Master <- Slave1 <- Slave2 <- Slave3…
這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1 做 Master,其他不變。
三十、Redis 提供了哪幾種持久化方式
【1】RDB 持久化方式能夠在指定的時間間隔能對你的數據進行快照存儲。
【2】AOF 持久化方式記錄每次對服務器寫的操作,當服務器重啟的時候會重新執行這些命令來恢復原始的數據。AOF命令以redis協議追加保存每次寫的操作到文件末尾。Redis 還能對 AOF文件進行后臺重寫,使得AOF文件的體積不至于過大。
【3】如果你只希望你的數據在服務器運行的時候存在,你也可以不使用任何持久化方式。
【4】你也可以同時開啟兩種持久化方式,在這種情況下,當 Redis 重啟的時候會優先載入 AOF文件來恢復原始的數據,因為在通常情況下 AOF文件保存的數據集要比 RDB文件保存的數據集要完整。
【5】最重要的事情是了解 RDB和 AOF持久化方式的不同,讓我們以RDB持久化方式開始。
三十一、如何選擇合適的持久化方式
一般來說, 如果想達到足以媲美 PostgreSQL的數據安全性, 你應該同時使用兩種持久化功能。如果你非常關心你的數據, 但仍然可以承受數分鐘以內的數據丟失,那么你可以只使用 RDB持久化。有很多用戶都只使用 AOF持久化,但并不推薦這種方式:因為定時生成RDB快照(snapshot)非常便于進行數據庫備份, 并且 RDB 恢復數據集的速度也要比 AOF恢復的速度要快,除此之外, 使用 RDB還可以避免之前提到的 AOF 程序的 bug。
三十二、修改配置不重啟 Redis會實時生效嗎
針對運行實例,有許多配置選項可以通過 CONFIG SET 命令進行修改,而無需執行任何形式的重啟。 從 Redis 2.2 開始,可以從 AOF 切換到 RDB 的快照持久性或其他方式而不需要重啟 Redis。檢索 ‘CONFIG GET *’ 命令獲取更多信息。但偶爾重新啟動是必須的,如為升級 Redis 程序到新的版本,或者當你需要修改某些目前 CONFIG 命令還不支持的配置參數的時候。
三十三、Redis 中的哨兵模式(sentinel) 的作用
典型的問題就是,當主節點宕機后,sentinel 是如何進行主從切換的。
哨兵(sentinel)三大作用:
【1】監控: 哨兵Sentinel會不斷檢查您的master和slave是否按預期工作。
【2】自動故障恢復: 如果master故障,哨兵集群會選出一個哨兵,這個哨兵會選出其中的一個slave提升為master。當之前的master故障實例恢復后變為新的master的slave。
【3】通知: Sentinel充當Redis客戶端的服務發現來源,當集群發生故障轉移時,會將最新信息推送給Redis的客戶端。
哨兵集群監控原理(Sentinel如何判斷一個redis實例是否健康?): 哨兵Sentinel集群基于心跳機制監測服務狀態,每隔1秒向集群的每個實例發送ping命令:
【1】主觀下線: 如果某sentinel節點發現某實例未在規定時間響應,則認為該實例主觀下線。
【2】客觀下線: 若超過指定數量(quorum)的sentinel都認為該實例主觀下線,則判定該實例客觀下線即服務下線。
quorum的值可自由設置,最好設置為超過Sentinel實例數量的一半。
集群故障恢復原理流程: 一旦發現master故障時
【1】哨兵sentine集群會先選舉一個領頭哨兵Sentinel,并由領頭哨兵Sentinel對下線主服務器執行故障轉移操作。
【2】領頭Sentinel根據選舉規則選出一個slave提升為新的master,sentinel給選舉出來的slave節點發送slaveof no one 命令,讓該節點成為新master。(選master)
【3】sentinel給所有其它slave發送slaveof 新master的IP 新master的port 命令,讓這些slave成為新master的從節點,開始從新的master上同步數據。(建立新連接)
【4】最后,哨兵sentinel將故障節點標記為slave,當故障節點恢復后會自動成為新的master的slave節點。(故障恢復成為slave)
新的master選舉依據:
【1】首先會判斷slave節點與master節點斷開時間長短,如果超過指定值(down-after-milliseconds 10)則會排除該slave節點
【2】然后判斷slave節點的slave-priority值,越小優先級越高,如果是0則永不參與選舉
【3】如果slave-prority一樣,則判斷slave節點的offset值,越大說明數據越新,優先級越高
【4】最后是判斷slave節點的運行id大小,越小優先級越高。
三十四、談談你對 Redis 集群 Cluster的理解
【博客連接】:鏈接
三十五、Redis 的常用配置有哪些
【博客連接】:鏈接
三十六、Redis 的線程模型
【博客連接】:鏈接
三十七、Redis 分布式鎖的理解
【博客連接】:鏈接
三十八、Redis 平常用到的調優
Redis 大 Key 改造案例???????
三十九、Scan 命令的使用
scan 提供了三個參數,第一個是 cursor 整數值,第二個是 key 的正則模式,第三個是遍歷的 limit hint。第一次遍歷時,cursor 值為 0,然后將返回結果中第一個整數值作為下一次遍歷的 cursor,一直遍歷到返回的 cursor 值為 0時結束。舉個栗子:
127.0.0.1:6379> scan 0 match key99* count 1000
1) "13976"
2) 1) "key9933"2) 此處省略9個
從上面的過程中可以看出,雖然提供的 limit 是 1000,但是返回的結果卻只有 10個左右。因為這個 limit 不是限定返回結果的數量,而是限定服務器單次遍歷的字典槽數量(約等于)。返回的值是游標,目前游標的值不為零,意味著遍歷還沒有結束。
四十、Redis 事務相關的命令有哪幾個
MULTI、EXEC、DISCARD、WATCH、UNWATCH
四十一、Redis 中時間復雜度為 O(n) 的命令
List: lindex、lset、linsert;
Hash: hgetall、hkeys、hvals;
Set: smembers、sunion、sunionstore、sinter、sinterstore、sdiff、sdiffstore;
Sorted Set:zrange、zrevrange、zrangebyscore、zrevrangebyscore、zremrangebyrank、zremrangebyscore;
四十二、ZSet進行排序的上限是多少?
在Redis中,ZSet(有序集合)可以存儲非常大的元素數量,并且可以根據分數(score)對元素進行排序。根據Redis的文檔,ZSet的排序上限是2^32-1,即4294967295。
這意味著你可以在一個ZSet中存儲最多4294967295個元素,并且可以根據分數對它們進行排序。請注意,這個上限是針對每個ZSet的總元素數量,而不是每個分數的唯一元素數量。
需要注意的是,存儲大量的元素會占用更多的內存,并且在執行排序操作時可能會對性能產生影響。因此,在使用ZSet時,需要根據實際需求和系統資源來評估和調整數據量。
四十三、Redis 中 key是怎么設置的?
【1】建議全部大寫;
【2】key不能太長也不能太短,鍵名越長越占資源,太短可讀性太差;
【3】key 單詞與單詞之間以 :分開;
【4】Redis 使用的時候注意命名空間,一個項目一個命名空間,項目內業務不同命名空間也不同。一般情況下: 1) 第一段放置項目名或縮寫 如 project: 2) 第二段把表名轉換為 key前綴 如 user: 3) 第三段放置用于區分區 key的字段,對應 Mysql中的主鍵的列名,如userid: 4) 第四段放置主鍵值,如18,16;結合起來 PRO:USER:UID:18 是不是很清晰;
【5】設置過期時間,節省內存;
四十四、怎么防止消息丟失
兩種數據丟失的情況:
【1】主備切換的過程,可能導致數據丟失:因為master 到 slave的復制是異步的,所以可能有部分數據還沒復制到slave,master就宕機了,此時這些部分數據就丟失了,如果主從延遲特別大,那么丟失的數據就可能會特別多;
【2】腦裂導致的數據丟失: 腦裂就是說,某個 maser 所在機器突然脫離了正常的網絡,跟其他 slave機器不能連接,但是實際上 master還運行著,此時哨兵可能就會認為 master 宕機了,然后開啟選舉,將其他 slave切換成了 master,這個時候,集群里面就會有2個 master,也就是所謂的腦裂,此時雖然某個 slave被切換成了master,但是可能 client還沒來得及切換到新的 master,還繼續寫向舊 master的數據可能也丟失了,因此 master再次恢復的時候,會被作為一個 slave掛到新的 master 上去,自己的數據將會清空,重新從新的 master 復制數據;
解決異步復制和腦裂導致的數據丟失
# redis.conf 配置
min-slaves-to-write 1 #給指定數量的 slave發送數據
min-slaves-max-lag 10 #salve 返回 ack的超時時間
上面這兩個配置可以減少異步復制和腦裂導致的數據丟失;
減少異步復制的數據丟失: 有了 min-slaves-max-lag這個配置,可以確保說,一旦 slave復制數據和 ack延遲太長,就認為可能 master 宕機后損失的數據太多了,那么就拒絕寫請求,這樣可以盡量減少 master宕機時由于部分數據丟失。如果想要強一致性就需要犧牲效率,增加 Raft協議,來增加強一致性。
減少腦裂的數據丟失: 如果一個 master出現了腦裂,跟其他 slave丟了連接,那么上面這兩個配置可以去確保說,如果不能繼續給指定數量的 slave發送數據,而且 slave超過10秒沒有給自己 ack消息,那么就直接拒絕客戶端的寫請求,這樣腦裂活的舊 master就不會接受 client的新數據,也就避免了數據丟失,上面配置確保了,如果跟任何一個 slave丟了連接,在 10秒后發現沒有 slave給自己 ack,那么就拒絕新的寫請求,因此腦裂場景下,最多丟失 10秒的數據。
aof 增量持久化數據:aof 持久化最多丟失1秒的數據
四十五、Redis的 AOF文件占用過大
使用云服務器的時候,給Redis用了 32G內存,但是 AOF文件就達到了128G。經常出現如下報錯:
Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
解決辦法:使用 BGREWRITEAOF,可以優化 aof文件。即使 BGREWRITEAOF執行失敗,也不會有任何數據丟失,因為舊的 AOF 文件在 BGREWRITEAOF成功之前不會被修改。重寫操作只會在沒有其他持久化工作在后臺執行時被觸發,也就是說:如果 Redis 的子進程正在執行快照的保存工作,那么 AOF 重寫的操作會被預定(scheduled),等到保存工作完成之后再執行 AOF 重寫。在這種情況下, BGREWRITEAOF的返回值仍然是 OK ,但還會加上一條額外的信息,說明 BGREWRITEAOF要等到保存操作完成之后才能執行。在 Redis 2.6 或以上的版本,可以使用 INFO 命令查看 BGREWRITEAOF是否被預定。
如果已經有別的 AOF 文件重寫在執行,那么 BGREWRITEAOF返回一個錯誤,并且這個新的 BGREWRITEAOF請求也不會被預定到下次執行。從 Redis 2.4 開始, AOF 重寫由 Redis 自行觸發, BGREWRITEAOF僅僅用于手動觸發重寫操作。自動觸發需要修改 redis.conf文件
auto-aof-rewrite-percentage 50
然后重啟Redis,這段配置,是指當 aof文件增值率達到 50%時,優化一次 aof,也就是執行 BGREWRITEAOF命令,默認是100,因為線上寫入比較頻率,所以增長率要調低一點。之前 100多個G的 aof,重寫一次之后,降至30G。
如果你的不能自動觸發,可以寫一個腳本去執行:brgewriteaof.sh
#!/bin/bash
/usr/local/redis/redis-cli -p 6379 -h 127.0.0.1 BGREWRITEAOF
# 添加權限
chmod 755 brgewriteaof.sh
# 設定任務計劃,每天凌晨2點跑一次
0 2 * * * /opt/brgewriteaof.sh
重寫的好處: 減少 AOF日志尺寸,減少內存占用,加快數據庫恢復時間。