很火的Redis入門精講(二)

在昨天的文章中,我們介紹了Redis的概念、特點、性能、併發、安裝使用Redis的原因以及Redis數據結構等內容。如果想了解以上內容的,請移步昨天的文章哦!今天我們繼續說說Redis。

很火的Redis入門精講(二)

聊聊主從 – 用法

像MySQL一樣,redis是支持主從同步的,而且也支持一主多從以及多級從結構。

主從結構,一是為了純粹的冗餘備份,二是為了提升讀性能,比如很消耗性能的SORT就可以由從服務器來承擔。

redis的主從同步是異步進行的,這意味著主從同步不會影響主邏輯,也不會降低redis的處理性能。

主從架構中,可以考慮關閉主服務器的數據持久化功能,只讓從服務器進行持久化,這樣可以提高主服務器的處理性能。

在主從架構中,從服務器通常被設置為只讀模式,這樣可以避免從服務器的數據被誤修改。但是從服務器仍然可以接受CONFIG等指令,所以還是不應該將從服務器直接暴露到不安全的網絡環境中。如果必須如此,那可以考慮給重要指令進行重命名,來避免命令被外人誤執行。

很火的Redis入門精講(二)

聊聊主從 – 同步原理

從服務器會向主服務器發出SYNC指令,當主服務器接到此命令後,就會調用BGSAVE指令來創建一個子進程專門進行數據持久化工作,也就是將主服務器的數據寫入RDB文件中。在數據持久化期間,主服務器將執行的寫指令都緩存在內存中。

在BGSAVE指令執行完成後,主服務器會將持久化好的RDB文件發送給從服務器,從服務器接到此文件後會將其存儲到磁盤上,然後再將其讀取到內存中。這個動作完成後,主服務器會將這段時間緩存的寫指令再以redis協議的格式發送給從服務器。

另外,要說的一點是,即使有多個從服務器同時發來SYNC指令,主服務器也只會執行一次BGSAVE,然後把持久化好的RDB文件發給多個下游。在redis2.8版本之前,如果從服務器與主服務器因某些原因斷開連接的話,都會進行一次主從之間的全量的數據同步;而在2.8版本之後,redis支持了效率更高的增量同步策略,這大大降低了連接斷開的恢復成本。

主服務器會在內存中維護一個緩衝區,緩衝區中存儲著將要發給從服務器的內容。從服務器在與主服務器出現網絡瞬斷之後,從服務器會嘗試再次與主服務器連接,一旦連接成功,從服務器就會把“希望同步的主服務器ID”和“希望請求的數據的偏移位置(replication offset)”發送出去。主服務器接收到這樣的同步請求後,首先會驗證主服務器ID是否和自己的ID匹配,其次會檢查“請求的偏移位置”是否存在於自己的緩衝區中,如果兩者都滿足的話,主服務器就會向從服務器發送增量內容。

增量同步功能,需要服務器端支持全新的PSYNC指令。這個指令,只有在redis-2.8之後才具有。

很火的Redis入門精講(二)

redis的事務處理

眾所周知,事務是指“一個完整的動作,要麼全部執行,要麼什麼也沒有做”。

在聊redis事務處理之前,要先和大家介紹四個redis指令,即MULTI、EXEC、DISCARD、WATCH。這四個指令構成了redis事務處理的基礎。

1.MULTI用來組裝一個事務;

2.EXEC用來執行一個事務;

3.DISCARD用來取消一個事務;

4.WATCH用來監視一些key,一旦這些key在事務執行之前被改變,則取消事務的執行。

紙上得來終覺淺,我們來看一個MULTI和EXEC的例子:

很火的Redis入門精講(二)

在上面的例子中,我們看到了QUEUED的字樣,這表示我們在用MULTI組裝事務時,每一個命令都會進入到內存隊列中緩存起來,如果出現QUEUED則表示我們這個命令成功插入了緩存隊列,在將來執行EXEC時,這些被QUEUED的命令都會被組裝成一個事務來執行。

對於事務的執行來說,如果redis開啟了AOF持久化的話,那麼一旦事務被成功執行,事務中的命令就會通過write命令一次性寫到磁盤中去,如果在向磁盤中寫的過程中恰好出現斷電、硬件故障等問題,那麼就可能出現只有部分命令進行了AOF持久化,這時AOF文件就會出現不完整的情況,這時,我們可以使用redis-check-aof工具來修復這一問題,這個工具會將AOF文件中不完整的信息移除,確保AOF文件完整可用。

有關事務,大家經常會遇到的是兩類錯誤:

1.調用EXEC之前的錯誤

2.調用EXEC之後的錯誤

“調用EXEC之前的錯誤”,有可能是由於語法有誤導致的,也可能時由於內存不足導致的。只要出現某個命令無法成功寫入緩衝隊列的情況,redis都會進行記錄,在客戶端調用EXEC時,redis會拒絕執行這一事務。(這時2.6.5版本之後的策略。在2.6.5之前的版本中,redis會忽略那些入隊失敗的命令,只執行那些入隊成功的命令)。我們來看一個這樣的例子:

很火的Redis入門精講(二)

而對於“調用EXEC之後的錯誤”,redis則採取了完全不同的策略,即redis不會理睬這些錯誤,而是繼續向下執行事務中的其他命令。這是因為,對於應用層面的錯誤,並不是redis自身需要考慮和處理的問題,所以一個事務中如果某一條命令執行失敗,並不會影響接下來的其他命令的執行。我們也來看一個例子:

很火的Redis入門精講(二)

好了,我們來說說最後一個指令“WATCH”,這是一個很好用的指令,它可以幫我們實現類似於“樂觀鎖”的效果,即CAS(check and set)。

WATCH本身的作用是“監視key是否被改動過”,而且支持同時監視多個key,只要還沒真正觸發事務,WATCH都會盡職盡責的監視,一旦發現某個key被修改了,在執行EXEC時就會返回nil,表示事務無法觸發。

很火的Redis入門精講(二)

教你看懂redis配置 – 簡介:

我們可以在啟動redis-server時指定應該加載的配置文件,方法如下:

很火的Redis入門精講(二)

接下來,我們就來講解下redis配置文件的各個配置項的含義,注意,本文是基於redis-2.8.4版本進行講解的。

redis官方提供的redis.conf文件,足有700+行,其中100多行為有效配置行,另外的600多行為註釋說明。

在配置文件的開頭部分,首先明確了一些度量單位:

很火的Redis入門精講(二)

可以看出,redis配置中對單位的大小寫不敏感,1GB、1Gb和1gB都是相同的。由此也說明,redis只支持bytes,不支持bit單位。

redis支持“主配置文件中引入外部配置文件”,很像C/C++中的include指令,比如:

很火的Redis入門精講(二)

如果你看過redis的配置文件,會發現還是很有條理的。redis配置文件被分成了幾大塊區域,它們分別是:

很火的Redis入門精講(二)

下面我們就來逐一講解。

教你看懂redis配置 -通用

默認情況下,redis並不是以daemon形式來運行的。通過daemonize配置項可以控制redis的運行形式,如果改為yes,那麼redis就會以daemon形式運行:

很火的Redis入門精講(二)

當以daemon形式運行時,redis會生成一個pid文件,默認會生成在/var/run/redis.pid。當然,你可以通過pidfile來指定pid文件生成的位置,比如:

很火的Redis入門精講(二)

默認情況下,redis會響應本機所有可用網卡的連接請求。當然,redis允許你通過bind配置項來指定要綁定的IP,比如:

很火的Redis入門精講(二)

redis的默認服務端口是6379,你可以通過port配置項來修改。如果端口設置為0的話,redis便不會監聽端口了。

很火的Redis入門精講(二)

有些同學會問“如果redis不監聽端口,還怎麼與外界通信呢”,其實redis還支持通過unix socket方式來接收請求。可以通過unixsocket配置項來指定unix socket文件的路徑,並通過unixsocketperm來指定文件的權限。

很火的Redis入門精講(二)

當一個redis-client一直沒有請求發向server端,那麼server端有權主動關閉這個連接,可以通過timeout來設置“空閒超時時限”,0表示永不關閉。

很火的Redis入門精講(二)

TCP連接保活策略,可以通過tcp-keepalive配置項來進行設置,單位為秒,假如設置為60秒,則server端會每60秒向連接空閒的客戶端發起一次ACK請求,以檢查客戶端是否已經掛掉,對於無響應的客戶端則會關閉其連接。所以關閉一個連接最長需要120秒的時間。如果設置為0,則不會進行保活檢測。

很火的Redis入門精講(二)

redis支持通過loglevel配置項設置日誌等級,共分四級,即debug、verbose、notice、warning。

很火的Redis入門精講(二)

redis也支持通過logfile配置項來設置日誌文件的生成位置。如果設置為空字符串,則redis會將日誌輸出到標準輸出。假如你在daemon情況下將日誌設置為輸出到標準輸出,則日誌會被寫到/dev/null中。

很火的Redis入門精講(二)

如果希望日誌打印到syslog中,也很容易,通過syslog-enabled來控制。另外,syslog-ident還可以讓你指定syslog裡的日誌標誌,比如:

很火的Redis入門精講(二)

而且還支持指定syslog設備,值可以是USER或LOCAL0-LOCAL7。具體可以參考syslog服務本身的用法。

很火的Redis入門精講(二)

對於redis來說,可以設置其數據庫的總數量,假如你希望一個redis包含16個數據庫,那麼設置如下:

很火的Redis入門精講(二)

這16個數據庫的編號將是0到15。默認的數據庫是編號為0的數據庫。用戶可以使用select 來選擇相應的數據庫。

教你看懂redis配置 – 快照

快照,主要涉及的是redis的RDB持久化相關的配置,我們來一起看一看。

我們可以用如下的指令來讓數據保存到磁盤上,即控制RDB快照功能:

很火的Redis入門精講(二)

舉例來說:

很火的Redis入門精講(二)

如果你想禁用RDB持久化的策略,只要不設置任何save指令就可以,或者給save傳入一個空字符串參數也可以達到相同效果,就像這樣:

很火的Redis入門精講(二)

如果用戶開啟了RDB快照功能,那麼在redis持久化數據到磁盤時如果出現失敗,默認情況下,redis會停止接受所有的寫請求。這樣做的好處在於可以讓用戶很明確的知道內存中的數據和磁盤上的數據已經存在不一致了。如果redis不顧這種不一致,一意孤行的繼續接收寫請求,就可能會引起一些災難性的後果。

如果下一次RDB持久化成功,redis會自動恢復接受寫請求。

當然,如果你不在乎這種數據不一致或者有其他的手段發現和控制這種不一致的話,你完全可以關閉這個功能,以便在快照寫入失敗時,也能確保redis繼續接受新的寫請求。配置項如下:

很火的Redis入門精講(二)

對於存儲到磁盤中的快照,可以設置是否進行壓縮存儲。如果是的話,redis會採用LZF算法進行壓縮。如果你不想消耗CPU來進行壓縮的話,可以設置為關閉此功能,但是存儲在磁盤上的快照會比較大。

很火的Redis入門精講(二)

在存儲快照後,我們還可以讓redis使用CRC64算法來進行數據校驗,但是這樣做會增加大約10%的性能消耗,如果你希望獲取到最大的性能提升,可以關閉此功能。

很火的Redis入門精講(二)

我們還可以設置快照文件的名稱,默認是這樣配置的:

很火的Redis入門精講(二)

最後,你還可以設置這個快照文件存放的路徑。比如默認設置就是當前文件夾:

很火的Redis入門精講(二)

教你看懂redis配置 – 複製

redis提供了主從同步功能。

通過slaveof配置項可以控制某一個redis作為另一個redis的從服務器,通過指定IP和端口來定位到主redis的位置。一般情況下,我們會建議用戶為從redis設置一個不同頻率的快照持久化的週期,或者為從redis配置一個不同的服務端口等等。

很火的Redis入門精講(二)

如果主redis設置了驗證密碼的話(使用requirepass來設置),則在從redis的配置中要使用masterauth來設置校驗密碼,否則的話,主redis會拒絕從redis的訪問請求。

很火的Redis入門精講(二)

當從redis失去了與主redis的連接,或者主從同步正在進行中時,redis該如何處理外部發來的訪問請求呢?這裡,從redis可以有兩種選擇:

第一種選擇:如果slave-serve-stale-data設置為yes(默認),則從redis仍會繼續響應客戶端的讀寫請求。

第二種選擇:如果slave-serve-stale-data設置為no,則從redis會對客戶端的請求返回“SYNC with master in progress”,當然也有例外,當客戶端發來INFO請求和SLAVEOF請求,從redis還是會進行處理。

你可以控制一個從redis是否可以接受寫請求。將數據直接寫入從redis,一般只適用於那些生命週期非常短的數據,因為在主從同步時,這些臨時數據就會被清理掉。自從redis2.6版本之後,默認從redis為只讀。

很火的Redis入門精講(二)

只讀的從redis並不適合直接暴露給不可信的客戶端。為了儘量降低風險,可以使用rename-command指令來將一些可能有破壞力的命令重命名,避免外部直接調用。比如:

很火的Redis入門精講(二)

從redis會週期性的向主redis發出PING包。你可以通過repl_ping_slave_period指令來控制其週期。默認是10秒。

很火的Redis入門精講(二)

在主從同步時,可能在這些情況下會有超時發生:

1.以從redis的角度來看,當有大規模IO傳輸時。

2.以從redis的角度來看,當數據傳輸或PING時,主redis超時

3.以主redis的角度來看,在回覆從redis的PING時,從redis超時

用戶可以設置上述超時的時限,不過要確保這個時限比repl-ping-slave-period的值要大,否則每次主redis都會認為從redis超時。

很火的Redis入門精講(二)

我們可以控制在主從同步時是否禁用TCP_NODELAY。如果開啟TCP_NODELAY,那麼主redis會使用更少的TCP包和更少的帶寬來向從redis傳輸數據。但是這可能會增加一些同步的延遲,大概會達到40毫秒左右。如果你關閉了TCP_NODELAY,那麼數據同步的延遲時間會降低,但是會消耗更多的帶寬。(如果你不瞭解TCP_NODELAY,可以到這裡來科普一下)。

很火的Redis入門精講(二)

我們還可以設置同步隊列長度。隊列長度(backlog)是主redis中的一個緩衝區,在與從redis斷開連接期間,主redis會用這個緩衝區來緩存應該發給從redis的數據。這樣的話,當從redis重新連接上之後,就不必重新全量同步數據,只需要同步這部分增量數據即可。

很火的Redis入門精講(二)

如果主redis等了一段時間之後,還是無法連接到從redis,那麼緩衝隊列中的數據將被清理掉。我們可以設置主redis要等待的時間長度。如果設置為0,則表示永遠不清理。默認是1個小時。

很火的Redis入門精講(二)

我們可以給眾多的從redis設置優先級,在主redis持續工作不正常的情況,優先級高的從redis將會升級為主redis。而編號越小,優先級越高。比如一個主redis有三個從redis,優先級編號分別為10、100、25,那麼編號為10的從redis將會被首先選中升級為主redis。當優先級被設置為0時,這個從redis將永遠也不會被選中。默認的優先級為100。

很火的Redis入門精講(二)

假如主redis發現有超過M個從redis的連接延時大於N秒,那麼主redis就停止接受外來的寫請求。這是因為從redis一般會每秒鐘都向主redis發出PING,而主redis會記錄每一個從redis最近一次發來PING的時間點,所以主redis能夠了解每一個從redis的運行情況。

很火的Redis入門精講(二)

上面這個例子表示,假如有大於等於3個從redis的連接延遲大於10秒,那麼主redis就不再接受外部的寫請求。上述兩個配置中有一個被置為0,則這個特性將被關閉。默認情況下min-slaves-to-write為0,而min-slaves-max-lag為10。

更多編程資訊、乾貨持續更新中~


分享到:


相關文章: