分布式緩存技術redis學習系列(三)——redis高級應用(主從、事務與鎖、持久化)
上文《詳細講解redis數據結構(內存模型)以及常用命令》介紹了redis的數據類型以及常用命令,本文我們來學習下redis的一些高級特性。
回到頂部
安全性設置
設置客戶端操作秘密
redis安裝好後,默認情況下登陸客戶端和使用命令操作時不需要密碼的。某些情況下,為了安全起見,我們可以設置在客戶端連接後進行任何操作之前都要進行密碼驗證。修改redis.conf進行配置。
[[email protected] ~]# 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 foobared
requirepass redis129
# Command renaming.
如上,找到# requirepass foobared這一行,在下面添加“requirepass 密碼”一行設置密碼。設置好密碼後,有兩種方式授權客戶端進行操作。
客戶端授權方式
(1)登錄時使用-a參數指定客戶端密碼,如下
[[email protected] ~]# /usr/local/redis/bin/redis-cli -h 192.168.2.129 -p 6379 -a redis129
192.168.2.129:6379> keys *
1) "myzset"
192.168.2.129:6379>
(2)登錄客戶端後使用auth命令進行授權,如下
[[email protected] ~]# /usr/local/redis/bin/redis-cli -h 192.168.2.129 -p 6379
192.168.2.129:6379> keys *
(error) NOAUTH Authentication required.
192.168.2.129:6379> auth redis129
OK
192.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主從復制過程主要有下面幾步:
(1)從服務器都將向主服務器發送一個 SYNC 命令。
(2)主服務器接到 SYNC 命令後開啟一個後臺子進程並開始執行 BGSAVE,並在保存操作執行期間, 將所有新執行的寫入命令都保存到一個緩沖區裏面。
(3)當 BGSAVE 執行完畢後, 主服務器將執行保存操作所得的 .rdb 文件發送給從服務器, 從服務器接收這個 .rdb 文件, 並將文件中的數據載入到內存中。
(4)主服務器會以 Redis 命令協議的格式, 將寫命令緩沖區中積累的所有內容都發送給從服務器。
配置從服務器
redis配置一個從服務器非常簡單, 只要在從服務器的配置文件redis.conf中增加主服務器的IP地址和端口號就可以,如果主服務器設置了客戶端密碼,還需要在從服務器中配置主服務器的密碼,如下
##########################REPLICATION ###############################
# 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 <masterip> <masterport>
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 <master-password>
masterauth redis129
回到頂部事務與鎖
Redis 的事務支持相對簡單,MULTI 、 EXEC 、 DISCARD 和 WATCH 這四個命令是 Redis 事務的基礎。
事務開啟與取消
l MULTI 開啟一個事務。當客戶端發出了MULTI 命令時,客戶端和服務端的連接就進入了一個事務上下文的狀態。MULTI 執行之後, 客戶端可以繼續向服務器發送任意多條命令, 這些命令不會立即被執行, 而是被放到一個隊列中, 當 EXEC 命令被調用時, 所有隊列中的命令才會被執行。
l EXEC 順序執行事務隊列中的命令。
192.168.2.129:6379> multi
OK
192.168.2.129:6379> set name "zhangsan"
QUEUED
192.168.2.129:6379> set age 20
QUEUED
192.168.2.129:6379> exec
1) OK
2) OK
192.168.2.129:6379> keys *
1) "age"
2) "name"
192.168.2.129:6379>
l DISCARD 取消事務。當執行 DISCARD 命令時, 事務會被放棄, 事務隊列會被清空, 並且客戶端會從事務狀態中退出。
192.168.2.129:6379> multi
OK
192.168.2.129:6379> set name2 "lisi"
QUEUED
192.168.2.129:6379> set age 22
QUEUED
192.168.2.129:6379> discard
OK
192.168.2.129:6379> exec
(error) ERR EXEC without MULTI
192.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 name
OK
192.168.2.129:6379> multi
OK
192.168.2.129:6379> set name lisi
QUEUED
Client2 修改name
192.168.2.129:6379> get name
"huangliu"
192.168.2.129:6379> set name "wangwu"
OK
192.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文件,如下
######################### SNAPSHOTTING ################################
#
# 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 DB
dbfilename 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函數寫入命令到文件中的時機。如下
#######################APPEND ONLY MODE #############################
......
# 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) 1
192.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的集群。
參考文檔
http://redis.io/documentation
http://redisdoc.com/
分布式緩存技術redis學習系列(三)——redis高級應用(主從、事務與鎖、持久化)