如何保障reids的資料安全和效能?
一.持久化選項
1.快照snapshotting
它可以將存在於某一時刻的所有資料都寫入硬碟裡面。
配置選項示例: save 60 1000 注:從最近一次建立快照之後開始算起,60秒之內有1000次寫入滿足條件之後,redis開始快照儲存。
2.追加檔案(append-only-file) AOF
在執行命令時,將被執行的命令複製到硬碟裡面。
配置選項示例:appendonly no
兩種配置都要配置檔案輸出位置:
示例:dir /data/redis
注:將記憶體中的資料儲存到硬碟的一個主要原因就是為了重用資料,或者是為了防止系統故障而將資料備份到一個遠端位置。
二。快照持久化詳細
1 .快照的作用
redis可以通過建立快照來獲得儲存在記憶體裡面的資料在某個時間點上的副本。可以將快照複製到其他伺服器從而建立具有相同資料的伺服器副本,還可以將快照留在本地以便重啟伺服器時使用。
2.快照的缺點:
示例: 設定了60s 內 滿足1000條寫入命令 如果伺服器在剛剛滿足這個條件建立了快照,之後又小於1000條寫入命令 並且還沒有到60s, 這個時候伺服器崩潰了,那麼redis重啟之後,這些資料將會丟失。
因為快照了資料本身,如果資料量大的話,佔用磁碟也是一筆不小的開銷。
3.快照的優點:
重啟恢復快,儲存在本地,下次啟動資料恢復快。
4.建立快照的辦法
(1).客戶端傳送bgsave 命令來建立一個快照,redis會呼叫fork來建立一個子執行緒,然後負責將快照寫入硬碟,而父程式繼續處理命令請求。
(2).客戶端傳送save命令來建立一個快照,接受save命令的redis伺服器在快照建立完畢之前不在響應任何命令。一般不常用save命令,只有在沒有足夠記憶體下,或者等待持久化完畢也無所謂的情況下,才會使用這個命令。
(3)如果使用者設定了save選項,比如 save 60 1000 那麼從redis最近一次建立快照之後開始算起,滿足60s有1000個寫入命令就會呼叫bgsave命令。如果配置多個save選項,當有條件滿足就會觸發bgsave命令。
(4) 當一個redis伺服器連線另一個redis伺服器,並向對方傳送sync命令來開始一次複製操作的時候,如果主伺服器沒有執行bgsave操作,或者主伺服器並非剛剛執行完bgsave操作,那麼主伺服器就會執行bgsave命令。
注: 只使用快照來儲存資料時,如果系統傳送崩潰,使用者將丟失最近一次生成之後更改的所有資料。
三。AOF持久化詳細
如果使用者不能容忍資料的丟失,那麼可以使用aof持久化來儲存在記憶體裡的資料儘快地儲存到硬碟裡。
簡單的來說,aof持久化會將被執行的寫命令寫到aof檔案的末尾,以此來記錄資料發生的變化。
檔案同步,寫入檔案時會發生3件事,file.write()寫入的檔案會放在緩衝區,而資料只有寫到硬碟才算成功,使用者可以呼叫file.flush()這個操作是告訴作業系統儘快清空緩衝區,最後使用者還可以命令作業系統將檔案同步sync到硬碟,同步操作會一直阻塞知道指定檔案被寫入硬碟為止。
1.aof的appendonly3個同步頻率
always 每個寫入命令都要同步寫入到硬碟,這樣做會嚴重降低redis的速度
everysec 每秒執行一次同步,顯示地將多個寫命令到硬碟
no 讓作業系統來決定何時進行同步。
注: 如果使用了appendonly always 使用固態硬碟不斷寫入少量資料的做法可能會引發嚴重的寫入放大問題,在某些情況下會使固態硬碟的使用壽命降低。
為了兼顧資料安全和寫入效能,使用者可以考慮使用appendfsync everysec 讓redis每一秒的頻率對aop檔案進行同步,使用者也最多丟失一秒的資料。
aof持久化優點:
保證資料的安全性,並且減少效能消耗
aof持久化的缺點:
(1)使用者不斷的往aof檔案裡寫入日誌,體積不斷增大的aof檔案甚至可能用完硬碟空間。
(2)如果aof檔案的體積非常大,redis重啟通過aof檔案記錄的所有寫命令來還原資料集,那麼還原操作執行的時間就會可能非常長。
解決aof體積不斷增大的問題,可以向redis傳送bgrewriteaof命令,這個命令會通過移除aof檔案中冗餘命令來重寫aof,使aof檔案的體積儘可能變小。這個命令和bgsave的工作原理很相似,redis會建立一個子程式負責對aof檔案進行重寫。如果對體積比較大額aof重寫的話會造成作業系統掛起幾秒,可以按照設定快照一樣設定自動重寫aof的配置
可以通過設定auto-aof-rewrite-percentage 和 auto-aof-rewrire-min-size 選項來自動執行bgrewriteaof
示例: auto-aof-rewrite-percentage 100
auto-aof-rewrire-min-size 64mb
aof檔案達到64Mb 並且比上次重寫的aof檔案大一倍
無論使用快照還是aof這種方式,必須對持久化所得的檔案進行備份,最好是備份到不多的伺服器中去,這樣才能避免資料丟失事故發生。
四。複製
通過aof持久化或者快照持久化,可以在系統重啟或者崩潰的情況下仍然保留資料,隨著負載量的上升,或者資料的完整性變得越來越重要時,使用者可能需要使用複製特性。複製可以讓其他伺服器擁有一個不斷更新的資料副本,從而使得擁有資料副本的伺服器可以使用使用者處理客戶端傳送的請求。關聯式資料庫通常會使用一個主伺服器向多個從伺服器傳送更新,redis也採用同樣的方法實現自己的複製特性,並將作為一種擴充套件效能的一種手段。
1.複製配置
在建立快照方式中有redis伺服器向redis伺服器傳送sync命令也會出發bgsave命令,使用前提必須伺服器已經設定 dir 和dbfilename選項,並且這兩個目錄都是可寫的。
開啟從伺服器所必須的選項只有slaveof一個,在啟動redis伺服器的時候,指定一個包含slaveof host port 選項的配置檔案,那麼redis伺服器將根據選項給定的ip地址和埠來連線主伺服器,對應一個正在執行的redis伺服器,可以傳送slaveof no one 命令來讓伺服器終止複製曹操,不再接受主伺服器的資料更新,也可以用個傳送slaveod host port 命令來讓伺服器開始複製一個新的主伺服器。
2.複製過程
1.等待命令進入
2.開始執行bgsave,並使用緩衝區記錄bgsave之後執行的所有寫命令
3.bgsave執行完畢,向從伺服器傳送快照檔案,並在傳送期間繼續使用緩衝區記錄被執行的寫命令。
4。快照檔案傳送完畢,開始向從伺服器傳送儲存在緩衝區裡面的寫命令。
5.緩衝區儲存的寫命令傳送完畢,從現在開始,每執行一個寫命令,就向從伺服器傳送相同的寫命令。
一般主伺服器最好留足夠的記憶體和頻寬來執行復制到從伺服器中去,最好主伺服器只使用50%-65% 剩下的留給從伺服器使用。從服務型進行同步,會清空自己的所有資料,從伺服器在於伺服器進行初始連線時,資料庫中原有資料將會丟失,並替換成主伺服器發來的資料。
注: redis不支援主主複製。
3.檢查硬碟寫入
對於每秒同步aof檔案redis來說,可以通過傳送info命令 在輸出結果中 aof_pending_bio_fsync 屬性的值是否為0
至此: redis持久化的解決方案 使用aof和複製來保證資料安全和效能。
五. 處理系統故障
redis跟提供ACID保證的傳統關係資料不同,使用者需要多做一些工作才能保障資料的一致性
1.驗證快照檔案和aof檔案命令
redis-check-aof / redis-check-dump在系統崩潰之後,檢查aof檔案和快照檔案的狀態,並在需要的時候對檔案進行修復。
如果使用aof檔案, 那麼使用redis-chekc-aof --fix <file.aof> 掃描給定的aof檔案,目前沒有修復快照檔案的辦法,快照最好就是備份。
2.更換故障主伺服器
假設A,B兩臺執行著redis,其中A為主伺服器,如果A主伺服器崩潰了,如果讓C伺服器成為主伺服器
第一步向B傳送save命令,讓B建立一個快照檔案,接著將這個快照檔案發給機器C,並在機器C上啟動redis,最後讓B成為C的從伺服器。
redis還有一個哨兵模式 自動監控主伺服器掛掉之後會自動進行故障轉移。
3.redis事務
前面通過了multi將要執行的多個命令一起傳送給redis,除了這個之外只是保障redis按順序執行,還是不能防止其他redis客戶端對這些命令的鍵進行替換,更新,刪除操作,這是時候需要加上watch操作,如果發現對這些命令的鍵進行替換,更新和刪除,在使用者嘗試exec命令的時候,事務將失敗並返回一個錯誤,UNwatch命令可以在watch執行之後,multi命令執行之前對連線進行重置,同樣地,discard也可以在multi執行之後,exec執行值前對連線rest,也就是說,使用者在使用watch監視一個或多個鍵,接著開始使用multi開始一個新的事務,並將多個命令入佇列事務之後,仍然可以通過傳送discard來取消watch命令並清空所有已經入佇列的命令。
4.為什麼redis沒有實現典型的加鎖功能,關係型資料庫會對被訪問的資料進行加鎖,直到事務被提交或者被回滾為止。如果有客戶端試圖對被加鎖的資料進行寫入,那麼客戶端一直被阻塞。缺點在於效率低。屬於悲觀鎖
redis儘可能減少客戶端等待的時間,並不會在執行watch命令的時候加鎖,而是在其他客戶端修改了鍵的值,通知執行watch的客戶端,這種做法屬於樂觀鎖,只需要客戶端失敗重試就行。
redis提供了pipeline流水線執行redis的命令,減少通訊次數,如果設定pipeline傳入的引數為true,則會用multi和exec將命令包裹一起發給redis.如果為false 。redis只是將命令一條條的放在pipeline裡。這樣會減少通訊次數。
六。效能方面
如果要知道一個redis的命令到底跑多快。可以執行redis-benchmark 來了解redis在自己伺服器上的各種效能特徵。如果不給定引數的話,預設是50個客戶端進行效能測試
語法: redsi-benchmark -c 1 -q 注: -c是使用多少個客戶端 -q是讓程式簡化輸出結果
考察redis-benchmark 輸出結果是不要把結果看著事redis的實際效能。因為這個命令不會出來命令返回回覆,所以實際效能可能只有50%到60%。