Redis的事務只能保證不被打斷,不能保證回滾。
multi
op
op
op
exec
multi和exec的主要作用是移除競爭條件,并且可以減少客戶端和服務端之間的通信次數,提升性能。
$ setkey value
$ expire key 100
$ ttl key
Redis提供兩種資料持久化的方式,快照RDB和只追加檔案AOF。這兩種持久化的方式可以選擇性的使用。
save 60 1000
rdbcompression yes
dbfilename dump.
rdb
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
dir ./
以上就是一些簡單的持久化配置。對于快照檔案持久化,可能會丟失最近一次創建快照之后寫入的所有資料,快照檔案可以通過以下方式觸發。
1 客戶端向Redis發送BGSAVE-(background save)命令來創建快照。
2 客戶端向Redis發送SAVE命令來創建一個快照,Redis服務端在執行。
3 如果配置了save 60 10000表示60秒內完成10000此寫入就會觸發BGSAVE。
4 當Redis通過SHUTDOWN命令接收關閉服務器的請求時,或者接收到TERM信號時,會執行一個SAVE命令。
5 當一個Redis服務器連接另外一個Redis服務器,并向對方發送SYNC命令來開始一次復制操作時,如果主服務器沒有在執行BGSAVE操作,或者主服務器并非剛剛執行完BGSAVE操作,那么主服務器就會執行BGSAVE操作。
使用快照可能丟失資料,使用需謹慎,最好確定能夠丟失多長時間的資料,來設定Save操作,快照不能太頻繁,也不能太稀少。比如在我們處理日志檔案的時候,可以沒1000行將處理的進度存入Redis,即使程式崩潰,我們也可以繼續執行執行之前未完成的處理作業,我們還可以使用事務流水線來將進度和處理結果同時記錄到檔案里。
當Redis存盤的資料只有幾GB的時候,使用快照來保存資料是沒有問題的。可能比我們讀這句話的時間還要短。由于BGSAVE會開啟一個子行程去進行快照寫,因此需要剩余記憶體比較多,因此當Redis存盤了數十G的資料后,剩余記憶體不足夠的情況下,BGSAVE可能會導致系統長時間停頓,也可能導致大量的使用虛擬記憶體,導致Redis的性能降低到無法使用的程度,停頓的原因和Redis記憶體中存盤資料的多少成正比。在一臺68GB的Xen虛擬機上,對一個占用50GB記憶體的Redis服務器執行GBSAVE命令的話,光是創建子行程就需要花費15秒以上,而生成快照檔案更是需要15-20分鐘,這時候我們可以考慮使用SAVE命令,花費3-5分鐘就可以完成快照的生成作業,對于那些對快照次數不那么頻繁的程式,我們可以在不繁忙的情況下執行腳本來呼叫SAVE命令,然后備份生成的快照,然后繼續為客戶端繼續執行操作。
還是那句話,如果你允許資料的丟失,那么使用快照是一個不錯的選擇,否則可以使用AOF來將存盤在記憶體里面的資料盡快地保存到硬碟里。
檔案寫入=寫入緩沖區+通知作業系統盡快寫入硬碟+寫入硬碟。
使用Redis建議設定為每秒同步,這和不使用持久化時的性能相差無幾,這樣能保證即使程式崩潰也只丟失一秒的資料。但是AOF的檔案體積是一個問題,首先可能撐爆磁盤,也使得故障重啟時非常慢。這時候我們可以向Redis發送BGREWRITEAOF來移除AOF檔案中的冗余命令,這也會開啟一個后臺行程去執行重寫,我們也可以設定auto-aof-rewrite-percentage和auto-aof-rewrite-min-size來自動執行BGREWRITEAOF。
持久化是必須的,但是生成的持久化檔案我們必須進行備份,最好備份到多個不同的地方,這樣才能避免資料丟失,最好是將快照檔案和aof檔案備份到不同的服務器上面。
除了持久化,復制也是Redis的一大特性。和關系型資料庫一樣,Redis也主服務端向從服務端發送更新,并使用從服務端來處理所有讀請求。雖然,Redis性能特別優秀,但是也會遇上無法快速處理的情況,特別是在集合和有序集合進行操作的時候,涉及的元素可能會有成千上萬個甚至百萬個,在這種情況下,執行操作所花費的時間可能需要以秒來進行計算。一般情況下,一個正常的2.4GHZ的2處理器的服務器上對兩個10000元素的集合進行SUNIONSTORE會花費7-8毫秒。
我們可以使用SLAVEOF host port來讓slave接受主服務器的資料更新。從服務器連接主服務器之后會發送SYNC命令,主服務器執行BGSAVE并將所有的寫操作寫入緩沖區,發送BGSAVE,然后發送緩沖區的寫命令,緩沖區寫發送完畢之后,從現在開始每執行一個寫命令,都會向從服務器發送相同的寫命令。緩沖區需要記憶體,因此建議讓主服務器只使用50%-65%的記憶體,留下的記憶體用于執行BGSAVE和創建記錄寫命令的緩沖區。
使用SLAVEOF host port或使用SALVEOF命令都可以配置主從關系。如果是前者,那么Redis會在啟動時載入任何可用的快斬訓AOF檔案,然后執行復制程序。Redis不支持主主復制。當從服務器又有從服務器時,在發送BGSAVE檔案時,會導致從服務器的從服務器斷連重連。
當讀請求的重要性明顯高于寫,我們可以創建一顆多叉樹結構的主從鏈,來實作復制,通過使用AOF和復制,我們可以在丟失最少的情況下,將資料同步到多臺服務器。
我們還要檢查是否復制的內容是否已經寫入硬碟。首先我們得使用master_link_status是否為up來判斷從是否連接上,另外判斷資料是否同步到了從服務器,一般我們在寫入真正的資料之后往主服務器再寫入一條唯一的虛構值,看這個虛構值能不能到達從服務器。如何確定資料是否被寫入磁盤呢,這個就困難一點,使用INFO命令來查看aof_pending_bio_fsync屬性是否為0,如果是0,那就表示服務器已經將已知的所有資料寫入到了硬碟里。
查看服務端的綜合狀態可以使用Redis中的INFO命令來完成。
資料安全&性能保障
如果我們要將Redis作為唯一的資料存盤手段,我們就要確保Redis不會丟失任何資料。Redis沒有像傳統關系型資料庫那樣提供ACID保證可靠的資料事務,Redis只是一個軟體,即使硬體和軟體設計的完美無暇,也可能出現停電等突發情況。
當出現系統故障時,我們應該收下檢查aof檔案和dumpfile目錄,并且通過在redis-check-aof后面加上–fix引數,程式會對aof檔案進行掃描,發現錯誤命令則會洗掉該命令以及之后的所有命令。但是快照檔案無法修復,因此我們最好將快照檔案進行多處備份。
有了備份之后,我們在遇到故障主服務器時我們需要進行更換。首先向從服務B器發起SAVE命令,生成一個新的快照檔案,然后將快照檔案發送給機器C,并在機器C上啟動Redis,最后讓B成為C的從服務器。另外一種方法就是將從服務器升級為主服務器,然后為新的主服務器創建從服務器。當然這些操作都是人為的,可能出錯。我們可以使用Redis Sentinel監視指定的Redis主服務器以及其屬下的從服務器,并且在主服務器下線時自動進行故障轉移。
為了保證資料的正確性,我們需要使用Redis的事務。Redis的事務和傳統關系型資料庫并不相同,傳統的關系型資料庫支持回滾,但是Redis只能保證多個讀寫操作串行執行不被打斷。下面我們通過一種交易來學習下Redis事務,假設我們有一個需求,這個需求就是容許游戲玩家來出售自己的道具,玩家將自己的游戲道具放入市場里,如果有人購買了,那么玩家的賬戶會回應的增加資金,購買的那個玩家則會減少資金。
user:8888 -> {id: 8888,name: Jerry,funds: 43,}
inventory
:8888 ->[
item
:1001,
item
:1002,
item
:1003
]
market
: ->[
item
:1004:8888 | 58
]
在上面的資料結構中,將商品的id和玩家的id進行拼接起來,并且按出售價格將市場中的道具進行了排序,非常適合分頁和排序。在Redis的事務中,我們常常會用到如下的命令MULTI/EXEC、WATCH、UNWATCH/DISCARD等命令。UNWATCH可以在multi之前對將命令從事務佇列中移除,DISCARD可以在multi和exec之間將命令從事務佇列中移除。為了保證放入佇列的操作的原子性,我們需要監視玩家的包裹中元素的變化,只有當道具在用戶的包裹中時,后續才能將道具從玩家的包裹中移除到市場中,否則,這個將道具移到市場的操作就是無效的。
whilenotexpired
try
watch inventory
if notismember itemid of inventory
unwatch
return
multi
market: add item
inventory rem item
exec
returntrue
exception
passreturn false
同樣的購買行為也需要監視market:和購買者的個人資訊。如果用戶的資訊沒有被修改,并且market:的內容也沒有被修改,并且買家有足夠多錢的情況下,那么才會執行購買邏輯。
while notexpired // 保證方法能夠在一定時間后退出。try
watch market: buyer
if item price changed or buyer notable to buy
unwatch market: buyer
return
multi
//logic here
exec
returntrue
exception
passreturn false
監視market:是為了保證道具沒有被其他買家買走,監視買家是為了看買家是否有足夠的資金來購買道具,因為一個買家可能暫時沒有足夠的資金,但是自己在market:里的其他商品賣出后就可能有足夠的資金進行購買了。
Watch的本質是一種樂觀鎖,和Java中的CAS有點像。和傳統的關系型資料庫的悲觀鎖不一樣(有些的資料庫搜索引擎也實作了樂觀鎖MVCC),樂觀鎖的思想就是先干,干不成功就不成功,可以重試,也可以不再干。當多個客戶端同時對相同的資料進行操作時,正確的使用事務可以有效地防止資料錯誤發生。
雖然multi和exec很好用,但是它們也會消耗資源,可能導致其他重要的命令延遲執行,但是,我們可以使用非事務型流水線。使用pipeline(false)來開啟非事務流水線。
如果你想測驗Redis的性能,可以使用redis-benchmark工具。-c表示使用一個客戶端進行測驗,-q使用簡化輸出的結果格式。
$ redis-benchmark -c 1 -q
執行的結果如下所示,根據機器硬體配置會有所差異。

這種測驗出來的性能可能不真實,因為redis-benchmark不會處理執行命令所獲得的命令回復,節省了大量的語法分析時間。在不使用流水線的情況下,一般只能有上述50%-60%的性能。如果什么時候你的性能只有上面性能的25%左右,或者出現無法分配請求地址的情況,檢查一下你是不是創建了過多的連接。
Redis除了可以用來作為系統的一部分,還可以用來作為系統的支撐部分。比如可以用Redis來存盤日志和計數器來收集當前的狀態資訊,記錄配置資訊等等。
常見的記錄日志的方法有2種。第一種就是將日志記錄到檔案里面。第二種就是使用syslog服務來接收外部程式發來的日志訊息,并且支持路由日志存盤和日志清理作業。我們往往會使用syslog服務來記錄日志,這樣會方便很多,讓我們來使用Redis來保存最新的日志。
來源:https://developer.huawei.com/consumer/cn/forum/topicview?fid=23&tid=0201188042215490253
原作者: 穩哥很穩
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/24921.html
標籤:數據倉庫
上一篇:mysql分組后多條合一條
