持久化選項
持久化檔案存放的目錄:
dir ./
快照持久化(snapshotting)
儲存所有資料到磁碟
常見的配置:
save 60 1000stop-writes-on-bgsave-error nordbcompression yesdbfilename dump.rdb
建立快照有這麼幾種方法:
1,bgsave命令,會fork出一個進程
2,save命令,會造成在完成前,用戶端是去響應
3,配置save項
4,redis通過shutdown關閉時
5,當一個redis串連到另一個redis時,一般是主從複製時 追加檔案(AOF)
儲存所有執行的命令到磁碟
appendonly noappendfsync everysecno-appendfsync-on-rewrite noauto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb
appendfsync選項和同步頻率
選項 |
同步頻率 |
always |
每個redis命令都要同步到硬碟。這樣會嚴重影響redis的速度 |
everysec |
每秒執行一次同步 |
no |
讓作業系統來決定什麼時候進行同步 |
但是存在一個問題,aof檔案會越來越大,甚至遠遠大於快照檔案。為瞭解決這個問題,可以用bgrewriteaof,這個命令和bgsave一樣,會建立一個子進程來重寫aof檔案,移除冗餘命令。跟快照持久化一樣,aof也可以設定auto-aof-rewrite-percent選項和auto-aof-rewrite-min-size來自動執行bgrewriteaof。
無論採用哪種方式,都不足以保證資料安全。所以如果條件允許的話,最好能把資料備份到其他伺服器上,或者資料庫裡。 redis複製 主從複製
有經驗的工程師都知道複製(replication)是補課或缺的。複製可以讓其他伺服器擁有資料副本。redis也擁有這種能力。
非常簡單:
你需要設定dir和dbfilename選項。
然後安裝兩個redis伺服器,選擇一台作為備機,修改其redis.conf
slaveof <masterip> <masterport>
,開啟主redis,再開啟從redis。這樣你在主機上的資料就可以備份到從redis了。(從redis是不允許寫入資料的,而且從reids會拋棄掉之前擁有的所有資料)
開啟redis的主從複製並不需要太多的配置,不過瞭解其工作過程將會很有趣,也很有用。
從伺服器串連主伺服器時的步驟
步驟 |
主伺服器的操作 |
從伺服器的操作 |
1 |
等待命令進入 |
串連(或者重連)主伺服器,發送sync命令 |
2 |
開始執行bgsave,並使用緩衝區記錄bgsave之後執行的所有寫命令 |
根據配置選項來決定是繼續使用現有資料(如果有的話)來處理用戶端請求,還是想發送請求的用戶端返回錯誤 |
3 |
bgsave執行完畢,開始向從伺服器發送快照檔案,並在發送期間繼續使用緩衝區記錄執行的所有寫命令 |
丟棄舊資料,開始載入主伺服器發來的快照檔案 |
4 |
快照檔案發送完畢,開始向從伺服器發送儲存在緩衝區的寫命令 |
完成對快照檔案的解釋操作,想往常一樣接受命令請求 |
5 |
緩衝區儲存的命令發送完畢,從現在開始,沒執行一條寫命令,就向從伺服器發送相同的寫命令 |
執行主伺服器發來的所有儲存在緩衝區的寫命令;並從現在開始,接收並執行主伺服器發來的每個寫命令 |
警告:
1,redis不支援主主複製(master-master replication)。
2,從伺服器會刪掉所有資料。
當多個從伺服器嘗試串連同一個主伺服器時,情況又會變得不一樣
當有新的從伺服器串連主伺服器時 |
主伺服器的操作 |
上表的步驟3尚未執行 |
所有的從伺服器會接收到相同的快照檔案和相同的緩衝區命令 |
上表的步驟3正在執行或已經執行完畢 |
當主伺服器完成上表的5個步驟之後,再從步驟1執行到步驟5 |
主從鏈
redis的從伺服器和主伺服器並沒有什麼特別不同的地方,因此,從伺服器也可以擁有其從伺服器。
但是請注意其過程:如果從伺服器X擁有從伺服器Y,那麼當從伺服器X執行步驟4時,他會斷開與Y的串連,導致從伺服器Y需要重連並重新同步。
當讀請求的重要性遠遠高於寫請求,那麼可以建立一個由主從節點(master-slave node)組成的中介層來分擔主伺服器的複製工作。 redis事物
之前也介紹了事物,利用multi和exec就可以實現簡單的事物。但是存在一個問題:使用者沒辦法根據讀到的資料來做決定。比如,下訂單的時候,需要根據讀到的商品庫存量來決定是否可以下單。
為瞭解決這個問題,我們需要知道watch,有的時候還需要unwatch和discard命令。
__author__ = 'dubby'import redisimport timeconn = redis.Redis(host='localhost', port=6379, db=0)def list_item(itemid,sellerid,price): inventory = "inventory:%s"%sellerid item = "%s%s"(itemid,sellerid) end = time.time() + 5 pip = conn.pipeline() while time.time() < end: try: pip.watch(inventory) #監視使用者包裹發生的變化 if not pip.sismember(inventory,itemid): #檢查使用者是否堅持購買此商品 pip.unwatch() #如果使用者取消購買,取消監視,並退出 return None pip.multi() #開始購買 pip.zadd("market:",item,price) pip.srem(inventory,itemid) pip.execute() return True except redis.exception.EatchError: #如果在購買期間,發現使用者包裹出現變化,重試 pass return False
什麼是discard:unwatch可以在watch執行之後,multi執行之前對串連重設,discard可以在multi執行之後,exec執行之前對串連重設。 非事物型流水線
流水線(pipeline)除了事物,還可以緩衝命令,減少和redis伺服器的互動次數,但是有的時候不需要事物,僅僅需要緩衝命令,那麼可以
pip = conn.pipline(False)
這樣就可以獲得一個不帶事物的流水線