分散式快取技術Redis:高階應用(主從、事務與鎖、持久化)

安全性設定

設定客戶端操作秘密

redis安裝好後,預設情況下登陸客戶端和使用命令操作時不需要密碼的。某些情況下,為了安全起見,我們可以設定在客戶端連線後進行任何操作之前都要進行密碼驗證。修改redis。conf進行配置。

[root@localhost ~]# vi /usr/local/redis/etc/redis。conf

#######################SECURITY ##############################……# Warning: since Redis is pretty fast an outside user can try up to# 150k passwords per second against a good box。 This means that you should# use a very strong password otherwise it will be very easy to break。## requirepass foobaredrequirepass redis129 # Command renaming。

如上,找到# requirepass foobared這一行,在下面新增“requirepass 密碼”一行設定密碼。設定好密碼後,有兩種方式授權客戶端進行操作。

客戶端授權方式

(1)登入時使用-a引數指定客戶端密碼,如下

[root@localhost ~]# /usr/local/redis/bin/redis-cli -h 192。168。2。129 -p 6379 -a redis129192。168。2。129:6379> keys *1) “myzset”192。168。2。129:6379>

(2)登入客戶端後使用auth命令進行授權,如下

[root@localhost ~]# /usr/local/redis/bin/redis-cli -h 192。168。2。129 -p 6379192。168。2。129:6379> keys *(error) NOAUTH Authentication required。192。168。2。129:6379> auth redis129OK192。168。2。129:6379> keys *1) “myzset”192。168。2。129:6379>

主從複製

主從複製,即主伺服器與從伺服器之間資料備份的問題。Redis 支援簡單且易用的主從複製(master-slave replication)功能, 該功能可以讓從伺服器(slave server)成為主伺服器(master server)的精確複製品。

主從複製的特點

(1)一個主伺服器可以有多個從伺服器。

(2)不僅主伺服器可以有從伺服器, 從伺服器也可以有自己的從伺服器。

(3)Redis 支援非同步複製和部分複製(這兩個特性從Redis 2。8開始),主從複製過程不會阻塞主伺服器和從伺服器。

(4)主從複製功能可以提升系統的伸縮性和功能,如讓多個從伺服器處理只讀命令,使用複製功能來讓主伺服器免於頻繁的執行持久化操作。

主從複製的過程

下面我們用一個圖來講解redis主從複製的過程。

分散式快取技術Redis:高階應用(主從、事務與鎖、持久化)

Redis主從複製過程示意圖:

從上面的示意圖可以看出,主伺服器與從伺服器建立連線之後,Redis主從複製過程主要有下面幾步:

(1)從伺服器都將向主伺服器傳送一個 SYNC 命令。

(2)主伺服器接到 SYNC 命令後開啟一個後臺的程序並開始執行 BGSAVE,並在儲存操作執行期間, 將所有新執行的寫入命令都儲存到一個緩衝區裡面。

(3)當 BGSAVE 執行完畢後, 主伺服器將執行儲存操作所得的 。rdb 檔案傳送給從伺服器, 從伺服器接收這個 。rdb 檔案, 並將檔案中的資料載入到記憶體中。

(4)主伺服器會以 Redis 命令協議的格式, 將寫命令緩衝區中積累的所有內容都發送給從伺服器。

配置從伺服器

redis配置一個從伺服器非常簡單, 只要在從伺服器的配置檔案redis。conf中增加主伺服器的IP地址和埠號就可以,如果主伺服器設定了客戶端密碼,還需要在從伺服器中配置主伺服器的密碼,如下:

# Master-Slave replication。 Use slaveof to make a Redis instance a copy of# another Redis server。 A few things to understand ASAP about Redis replication。#……# slaveof slaveof 192。168。2。129 6379# If the master is password protected (using the “requirepass” configuration# directive below) it is possible to tell the slave to authenticate before# starting the replication synchronization process, otherwise the master will# refuse the slave request。## masterauth masterauth redis129

事務與鎖

Redis 的事務支援相對簡單,MULTI 、 EXEC 、 DISCARD 和 WATCH 這四個命令是 Redis 事務的基礎。

事務開啟與取消

l MULTI 開啟一個事務。當客戶端發出了MULTI 命令時,客戶端和服務端的連線就進入了一個事務上下文的狀態。MULTI 執行之後, 客戶端可以繼續向伺服器傳送任意多條命令, 這些命令不會立即被執行, 而是被放到一個佇列中, 當 EXEC 命令被呼叫時, 所有佇列中的命令才會被執行。

l EXEC 順序執行事務佇列中的命令。

192。168。2。129:6379> multiOK192。168。2。129:6379> set name “zhangsan”QUEUED192。168。2。129:6379> set age 20QUEUED192。168。2。129:6379> exec1) OK2) OK192。168。2。129:6379> keys *1) “age”2) “name”192。168。2。129:6379>

l DISCARD 取消事務。當執行 DISCARD 命令時, 事務會被放棄, 事務佇列會被清空, 並且客戶端會從事務狀態中退出。

192。168。2。129:6379> multiOK192。168。2。129:6379> set name2 “lisi”QUEUED192。168。2。129:6379> set age 22QUEUED192。168。2。129:6379> discardOK192。168。2。129:6379> exec(error) ERR EXEC without MULTI192。168。2。129:6379>

樂觀鎖

l WATCH 對key值進行鎖操作。 在 WATCH 執行之後, EXEC 執行之前, 在其他客戶端修改了 key 的值, 那麼當前客戶端的事務就會失敗。如下:

Client1開啟watch name並在事務中修改name,但是沒有執行exec

192。168。2。129:6379> get name“huangliu”192。168。2。129:6379> watch nameOK192。168。2。129:6379> multiOK192。168。2。129:6379> set name lisiQUEUED

Client2 修改name

192。168。2。129:6379> get name“huangliu”192。168。2。129:6379> set name “wangwu”OK192。168。2。129:6379> get name“wangwu”192。168。2。129:6379>

Client1執行exec

192。168。2。129:6379> exec(nil)192。168。2。129:6379>

可見,由於被watch的name已經被Client2 修改,所以Client1的事務執行失敗,程式需要做的, 就是不斷重試這個操作, 直到沒有發生碰撞(Crash)為止。

對key進行加鎖監視的機制類似Java多執行緒中的鎖(synchronized中的監視器物件),被稱作樂觀鎖。

樂觀是一種非常強大的鎖機制,後面我們會進一步學習redis的分散式鎖。

持久化機制

前面我們已經說過,既可以把redis理解為快取技術,也可以理解為資料庫,因為redis支援將記憶體中的資料週期性的寫入磁碟或者把操作追加到記錄檔案中,這個過程稱為redis的持久化。redis支援兩種方式的持久化,一種是快照方式(snapshotting),也稱RDB方式;另一種是追加檔案方式(append-only file),也稱AOF方式。RDB方式是redis預設的持久化方式。

RDB方式

RDB方式是將記憶體中的資料的快照以二進位制的方式寫入名字為 dump。rdb的檔案中。我們對 Redis 進行設定, 讓它根據設定週期性自動儲存資料集。修改redis。conf檔案,如下

## Save the DB on disk:……#   In the example below the behaviour will be to save:#   after 900 sec (15 min) if at least 1 key changed#   after 300 sec (5 min) if at least 10 keys changed#   after 60 sec if at least 10000 keys changed##   Note: you can disable saving completely by commenting out all “save” lines。##   It is also possible to remove all the previously configured save#   points by adding a save directive with a single empty string argument#   like in the following example:##   save “”#900秒內如果有超過1個key被修改則發起儲存快照save 900 1#300秒內如果有超過10個key被修改則發起儲存快照save 300 10#60秒內如果有超過1000個key被修改則發起儲存快照save 60 10000

dump。rdb檔案預設生成在%REDIS_HOME%etc目錄下(如/usr/local/redis/etc/),可以修改redis。conf檔案中的dir指定dump。rdb的儲存路徑

# The filename where to dump the DBdbfilename dump。rdb # The working directory。## The DB will be written inside this directory, with the filename specified# above using the ‘dbfilename’ configuration directive。## The Append Only File will also be created inside this directory。## Note that you must specify a directory here, not a file name。dir 。/

AOF方式

RDB方式是週期性的持久化資料, 如果未到持久化時間點,Redis 因為某些原因而造成故障停機, 那麼伺服器將丟失最近寫入、且仍未儲存到快照中的那些資料。所以從redis 1。1開始引入了AOF方式,AOF 持久化記錄伺服器執行的所有寫操作命令,並在伺服器啟動時,透過重新執行這些命令來還原資料集。 AOF 檔案中的命令全部以 Redis 協議的格式來儲存,新命令會被追加到檔案的末尾。

AOF方式仍然有丟失資料的可能,因為收到寫命令後可能並不會馬上將寫命令寫入磁碟,因此我們可以修改redis。conf,配置redis呼叫write函式寫入命令到檔案中的時機。如下

……# AOF and RDB persistence can be enabled at the same time without problems。# If the AOF is enabled on startup Redis will load the AOF, that is the file# with the better durability guarantees。## Please check http://redis。io/topics/persistence for more information。#啟用AOF方式appendonly yes#每次有新命令追加到 AOF 檔案時就執行一次 fsync :非常慢,也非常安全appendfsync always#每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的資料appendfsync everysec#從不 fsync :將資料交給作業系統來處理。更快,也更不安全的選擇appendfsync no

從上面三種AOF持久化時機來看,為了保證不丟失資料,appendfsync always是最安全的。

釋出以及訂閱訊息

Redis的釋出以及訂閱有點類似於聊天,是一種訊息通訊模式。在這個模式中,傳送者(傳送資訊的客戶端)不是將資訊直接傳送給特定的接收者(接收資訊的客戶端), 而是將資訊傳送給頻道(channel), 然後由頻道將資訊轉發給所有對這個頻道感興趣的訂閱者。SUBSCRIBE 、 UNSUBSCRIBE 和 PUBLISH 三個命令實現了訊息的釋出與訂閱。如下

Client1釋出頻道mychannel與訊息

192。168。2。129:6379> publish mychannel “message from channel1”(integer) 1192。168。2。129:6379>

Client2 訂閱頻道mychannel並接受Client1透過頻道發過來的訊息

192。168。2。129:6379>

subscribe mychannel

Reading messages。。。 (press Ctrl-C to quit)

1) “subscribe”

2) “mychannel”

3) (integer) 1

1) “message”

2) “mychannel”

3) “message from channel1”

至此,redis的客戶端安全性設定、主從複製、事務與鎖、持久化機制以及釋出與訂閱訊息主要內容介紹完畢。下一篇我們將繼續學習redis的叢集。