Redis配置詳解


我們說 Redis 相對於 Memcache 等其他的緩存產品,有一個比較明顯的優勢就是 Redis 不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。本篇博客我們就將介紹這些數據類型的詳細使用以及順帶介紹Redis系統的相關命令用法。

  注意:Redis的命令不區分大小寫,但是key 嚴格區分大小寫!!!

0、寫在前面

  下面介紹的Redis命令有很多,如果你想通過死記硬背來記住這些命令幾乎不可能,但是如果理解了Redis的一些機制,這些命令其實是由很強的通用性的,通過理解來記憶是最好的。 另外,每種數據類型都有其適合的使用場景,我也會在文中給與說明,如果濫用,反而會適得其反。

 

 

 

1、string 數據類型

  string 是Redis的最基本的數據類型,可以理解為與 Memcached 一模一樣的類型,一個key 對應一個 value。string 類型是二進制安全的,意思是 Redis 的 string 可以包含任何數據,比如圖片或者序列化的對象,一個 redis 中字符串 value 最多可以是 512M。

①、相關命令介紹

  string 數據類型在 Redis 中的相關命令:

  表格圖片引用:http://www.cnblogs.com/xrq730/p/8944539.html(下同)

  

   

  PS:

  ①、上面的 ttl 命令是返回 key 的剩余過期時間,單位為秒。

  ②、mset和mget這種批量處理命令,能夠極大的提高操作效率。因為一次命令執行所需要的時間=1次網絡傳輸時間+1次命令執行時間,n個命令耗時=n次網絡傳輸時間+n次命令執行時間,而批量處理命令會將n次網絡時間縮減為1次網絡時間,也就是1次網絡傳輸時間+n次命令處理時間。

  但是需要注意的是,Redis是單線程的,如果一次批量處理命令過多,會造成Redis阻塞或網絡擁塞(傳輸數據量大)。

  ③、setnx可以用於實現分布式鎖,具體實現方式后面會介紹。

  上面是 string 類型的基本命令,下面介紹幾個自增自減操作,這在實際工作中還是特別有用的(分布式環境中統計系統的在線人數,利用Redis的高性能讀寫,在Redis中完成秒殺,而不是直接操作數據庫。)。

  

   

②、典型使用場景

  一、計數

  由於Redis單線程的特點,我們不用考慮並發造成計數不准的問題,通過 incrby 命令,我們可以正確的得到我們想要的結果。

  二、限制次數

  比如登錄次數校驗,錯誤超過三次5分鍾內就不讓登錄了,每次登錄設置key自增一次,並設置該key的過期時間為5分鍾后,每次登錄檢查一下該key的值來進行限制登錄。

2、hash 數據類型

  hash 是一個鍵值對集合,是一個 string 類型的 key和 value 的映射表,key 還是key,但是value是一個鍵值對(key-value)。類比於 Java里面的 Map<String,Map<String,Object>> 集合。

①、相關命令介紹

   

   演示如下:

  

②、典型使用場景

  查詢的時間復雜度是O(1),用於緩存一些信息。

3、list 數據類型

  list 列表,它是簡單的字符串列表,按照插入順序排序,你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊),它的底層實際上是個鏈表。

  列表有兩個特點:

  一、有序

  二、可以重復

  這兩個特點要注意和后面介紹的集合和有序集合相對比。

①、相關命令介紹

  

   

  

②、典型使用場景

   一、棧

  通過命令 lpush+lpop

  二、隊列

  命令 lpush+rpop

  三、有限集合

  命令 lpush+ltrim

  四、消息隊列

  命令 lpush+brpop

4、set 數據類型

  Redis 的 set 是 string 類型的無序集合。

  相對於列表,集合也有兩個特點:

  一、無序

  二、不可重復

①、相關命令介紹

   

   

  

②、典型使用場景

  利用集合的交並集特性,比如在社交領域,我們可以很方便的求出多個用戶的共同好友,共同感興趣的領域等。

5、zset 數據類型

  zset(sorted set 有序集合),和上面的set 數據類型一樣,也是 string 類型元素的集合,但是它是有序的。

①、相關命令介紹

  

  

②、典型使用場景

  和set數據結構一樣,zset也可以用於社交領域的相關業務,並且還可以利用zset 的有序特性,還可以做類似排行榜的業務。

6、Redis5.0新數據結構-stream

  Redis的作者在Redis5.0中,放出一個新的數據結構,Stream。Redis Stream 的內部,其實也是一個隊列,每一個不同的key,對應的是不同的隊列,每個隊列的元素,也就是消息,都有一個msgid,並且需要保證msgid是嚴格遞增的。在Stream當中,消息是默認持久化的,即便是Redis重啟,也能夠讀取到消息。那么,stream是如何做到多播的呢?其實非常的簡單,與其他隊列系統相似,Redis對不同的消費者,也有消費者Group這樣的概念,不同的消費組,可以消費同一個消息,對於不同的消費組,都維護一個Idx下標,表示這一個消費群組消費到了哪里,每次進行消費,都會更新一下這個下標,往后面一位進行偏移。

 

7、系統相關命令

  

8、key 相關命令

  關於 key 的命令應該說是最常用的,需要大家記住。

  

   

  

  這里在介紹一個命令 :

OBJECT ENCODING    key  

  這是用來顯示這五種數據類型的底層數據結構,下一篇博客我們會詳細介紹。

  

   上面的命令我們給string 數據類型 k1 賦值 str,給 k2 賦值 123,通過 OBJECT ENCODING 顯示底層實現的數據類型分別是 embstr 和 int。這到底是什么呢?下篇博客我們會詳細介紹的。 

 

 前面我們說過,Redis 相對於 Memcache 等其他的緩存產品,有一個比較明顯的優勢就是 Redis 不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。這幾種豐富的數據類型我們花了兩篇文章進行了詳細的介紹,接下來我們要介紹 Redis 的另外一大優勢——持久化。

  由於 Redis 是一個內存數據庫,所謂內存數據庫,就是將數據庫中的內容保存在內存中,這與傳統的MySQL,Oracle等關系型數據庫直接將內容保存到硬盤中相比,內存數據庫的讀寫效率比傳統數據庫要快的多(內存的讀寫效率遠遠大於硬盤的讀寫效率)。但是保存在內存中也隨之帶來了一個缺點,一旦斷電或者宕機,那么內存數據庫中的數據將會全部丟失。

  為了解決這個缺點,Redis提供了將內存數據持久化到硬盤,以及用持久化文件來恢復數據庫數據的功能。Redis 支持兩種形式的持久化,一種是RDB快照(snapshotting),另外一種是AOF(append-only-file)。本篇博客先對 RDB 快照進行介紹。

1、RDB 簡介

  RDB是Redis用來進行持久化的一種方式,是把當前內存中的數據集快照寫入磁盤,也就是 Snapshot 快照(數據庫中所有鍵值對數據)。恢復時是將快照文件直接讀到內存里。

2、觸發方式

  RDB 有兩種觸發方式,分別是自動觸發和手動觸發。

①、自動觸發

  在 redis.conf 配置文件中的 SNAPSHOTTING 下,在這篇文章中我們介紹過。

  

  ①、save:這里是用來配置觸發 Redis的 RDB 持久化條件,也就是什么時候將內存中的數據保存到硬盤。比如“save m n”。表示m秒內數據集存在n次修改時,自動觸發bgsave(這個命令下面會介紹,手動觸發RDB持久化的命令)

  默認如下配置:

save 900 1:表示900 秒內如果至少有 1 個 key 的值變化,則保存
save 300 10:表示300 秒內如果至少有 10 個 key 的值變化,則保存
save 60 10000:表示60 秒內如果至少有 10000 個 key 的值變化,則保存

    當然如果你只是用Redis的緩存功能,不需要持久化,那么你可以注釋掉所有的 save 行來停用保存功能。可以直接一個空字符串來實現停用:save ""

  ②、stop-writes-on-bgsave-error :默認值為yes。當啟用了RDB且最后一次后台保存數據失敗,Redis是否停止接收數據。這會讓用戶意識到數據沒有正確持久化到磁盤上,否則沒有人會注意到災難(disaster)發生了。如果Redis重啟了,那么又可以重新開始接收數據了

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

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

  ⑤、dbfilename :設置快照的文件名,默認是 dump.rdb

  ⑥、dir:設置快照文件的存放路徑,這個配置項一定是個目錄,而不能是文件名。默認是和當前配置文件保存在同一目錄。

  也就是說通過在配置文件中配置的 save 方式,當實際操作滿足該配置形式時就會進行 RDB 持久化,將當前的內存快照保存在 dir 配置的目錄中,文件名由配置的 dbfilename 決定。

②、手動觸發

  手動觸發Redis進行RDB持久化的命令有兩種:

  1、save

  該命令會阻塞當前Redis服務器,執行save命令期間,Redis不能處理其他命令,直到RDB過程完成為止。

  顯然該命令對於內存比較大的實例會造成長時間阻塞,這是致命的缺陷,為了解決此問題,Redis提供了第二種方式。

  2、bgsave

  執行該命令時,Redis會在后台異步進行快照操作,快照同時還可以響應客戶端請求。具體操作是Redis進程執行fork操作創建子進程,RDB持久化過程由子進程負責,完成后自動結束。阻塞只發生在fork階段,一般時間很短。

  基本上 Redis 內部所有的RDB操作都是采用 bgsave 命令。

  ps:執行執行 flushall 命令,也會產生dump.rdb文件,但里面是空的.

3、恢復數據

  將備份文件 (dump.rdb) 移動到 redis 安裝目錄並啟動服務即可,redis就會自動加載文件數據至內存了。Redis 服務器在載入 RDB 文件期間,會一直處於阻塞狀態,直到載入工作完成為止。

  獲取 redis 的安裝目錄可以使用 config get dir 命令

  

  載入的標識是如下命令:

  

 

 

4、停止 RDB 持久化

  有些情況下,我們只想利用Redis的緩存功能,並不像使用 Redis 的持久化功能,那么這時候我們最好停掉 RDB 持久化。可以通過上面講的在配置文件 redis.conf 中,可以注釋掉所有的 save 行來停用保存功能或者直接一個空字符串來實現停用:save ""

  也可以通過命令:

1
redis-cli config set save  " "

5、RDB 的優勢和劣勢

  ①、優勢

  1.RDB是一個非常緊湊(compact)的文件,它保存了redis 在某個時間點上的數據集。這種文件非常適合用於進行備份和災難恢復。

  2.生成RDB文件的時候,redis主進程會fork()一個子進程來處理所有保存工作,主進程不需要進行任何磁盤IO操作。

  3.RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

  ②、劣勢

  1、RDB方式數據沒辦法做到實時持久化/秒級持久化。因為bgsave每次運行都要執行fork操作創建子進程,屬於重量級操作,如果不采用壓縮算法(內存中的數據被克隆了一份,大致2倍的膨脹性需要考慮),頻繁執行成本過高(影響性能)

  2、RDB文件使用特定二進制格式保存,Redis版本演進過程中有多個格式的RDB版本,存在老版本Redis服務無法兼容新版RDB格式的問題(版本不兼容)

  3、在一定間隔時間做一次備份,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改(數據有丟失)

6、RDB 自動保存的原理

  Redis有個服務器狀態結構:

1
2
3
4
5
6
7
8
9
struct  redisService{
      //1、記錄保存save條件的數組
      struct  saveparam *saveparams;
      //2、修改計數器
      long  long  dirty;
      //3、上一次執行保存的時間
      time_t  lastsave;
 
}

  ①、首先看記錄保存save條件的數組 saveparam,里面每個元素都是一個 saveparams 結構:

1
2
3
4
5
6
struct  saveparam{
      //秒數
      time_t  seconds;
      //修改數
      int  changes;
};

  前面我們在 redis.conf 配置文件中進行了關於save 的配置:

1
2
3
save 900 1:表示900 秒內如果至少有 1 個 key 的值變化,則保存
save 300 10:表示300 秒內如果至少有 10 個 key 的值變化,則保存
save 60 10000:表示60 秒內如果至少有 10000 個 key 的值變化,則保存

  那么服務器狀態中的saveparam 數組將會是如下的樣子:

  

  ②、dirty 計數器和lastsave 屬性

  dirty 計數器記錄距離上一次成功執行 save 命令或者 bgsave 命令之后,Redis服務器進行了多少次修改(包括寫入、刪除、更新等操作)。

  lastsave 屬性是一個時間戳,記錄上一次成功執行 save 命令或者 bgsave 命令的時間。

  通過這兩個命令,當服務器成功執行一次修改操作,那么dirty 計數器就會加 1,而lastsave 屬性記錄上一次執行save或bgsave的時間,Redis 服務器還有一個周期性操作函數 severCron ,默認每隔 100 毫秒就會執行一次,該函數會遍歷並檢查 saveparams 數組中的所有保存條件,只要有一個條件被滿足,那么就會執行 bgsave 命令。

  執行完成之后,dirty 計數器更新為 0 ,lastsave 也更新為執行命令的完成時間。

 

上一篇文章我們介紹了Redis的RDB持久化,RDB 持久化存在一個缺點是一定時間內做一次備份,如果redis意外down掉的話,就會丟失最后一次快照后的所有修改(數據有丟失)。對於數據完整性要求很嚴格的需求,怎么解決呢?

  本篇博客接着來介紹Redis的另一種持久化方式——AOF。

1、AOF簡介

  Redis的持久化方式之一RDB是通過保存數據庫中的鍵值對來記錄數據庫的狀態。而另一種持久化方式 AOF 則是通過保存Redis服務器所執行的寫命令來記錄數據庫狀態。

  比如對於如下命令:

  

  RDB 持久化方式就是將 str1,str2,str3 這三個鍵值對保存到 RDB文件中,而 AOF 持久化則是將執行的 set,sadd,lpush 三個命令保存到 AOF 文件中。

2、AOF 配置

  在 redis.conf 配置文件的 APPEND ONLY MODE 下:

  

  ①、appendonly:默認值為no,也就是說redis 默認使用的是rdb方式持久化,如果想要開啟 AOF 持久化方式,需要將 appendonly 修改為 yes。

  ②、appendfilename :aof文件名,默認是"appendonly.aof"

  ③、appendfsync:aof持久化策略的配置;

      no表示不執行fsync,由操作系統保證數據同步到磁盤,速度最快,但是不太安全;

      always表示每次寫入都執行fsync,以保證數據同步到磁盤,效率很低;

      everysec表示每秒執行一次fsync,可能會導致丟失這1s數據。通常選擇 everysec ,兼顧安全性和效率。

  ④、no-appendfsync-on-rewrite:在aof重寫或者寫入rdb文件的時候,會執行大量IO,此時對於everysec和always的aof模式來說,執行fsync會造成阻塞過長時間,no-appendfsync-on-rewrite字段設置為默認設置為no。如果對延遲要求很高的應用,這個字段可以設置為yes,否則還是設置為no,這樣對持久化特性來說這是更安全的選擇。   設置為yes表示rewrite期間對新寫操作不fsync,暫時存在內存中,等rewrite完成后再寫入,默認為no,建議yes。Linux的默認fsync策略是30秒。可能丟失30秒數據。默認值為no。

  ⑤、auto-aof-rewrite-percentage:默認值為100。aof自動重寫配置,當目前aof文件大小超過上一次重寫的aof文件大小的百分之多少進行重寫,即當aof文件增長到一定大小的時候,Redis能夠調用bgrewriteaof對日志文件進行重寫。當前AOF文件大小是上次日志重寫得到AOF文件大小的二倍(設置為100)時,自動啟動新的日志重寫過程。

  ⑥、auto-aof-rewrite-min-size:64mb。設置允許重寫的最小aof文件大小,避免了達到約定百分比但尺寸仍然很小的情況還要重寫。

  ⑦、aof-load-truncated:aof文件可能在尾部是不完整的,當redis啟動的時候,aof文件的數據被載入內存。重啟可能發生在redis所在的主機操作系統宕機后,尤其在ext4文件系統沒有加上data=ordered選項,出現這種現象  redis宕機或者異常終止不會造成尾部不完整現象,可以選擇讓redis退出,或者導入盡可能多的數據。如果選擇的是yes,當截斷的aof文件被導入的時候,會自動發布一個log給客戶端然后load。如果是no,用戶必須手動redis-check-aof修復AOF文件才可以。默認值為 yes。

3、開啟 AOF

  將 redis.conf 的 appendonly 配置改為 yes 即可。

  AOF 保存文件的位置和 RDB 保存文件的位置一樣,都是通過 redis.conf 配置文件的 dir 配置:

  

  可以通過 config get dir 命令獲取保存的路徑。

4、AOF 文件恢復

  重啟 Redis 之后就會進行 AOF 文件的載入。

  異常修復命令:redis-check-aof --fix 進行修復

5、 AOF 重寫

  由於AOF持久化是Redis不斷將寫命令記錄到 AOF 文件中,隨着Redis不斷的進行,AOF 的文件會越來越大,文件越大,占用服務器內存越大以及 AOF 恢復要求時間越長。為了解決這個問題,Redis新增了重寫機制,當AOF文件的大小超過所設定的閾值時,Redis就會啟動AOF文件的內容壓縮,只保留可以恢復數據的最小指令集。可以使用命令 bgrewriteaof 來重新。

  比如對於如下命令:

  

  如果不進行 AOF 文件重寫,那么 AOF 文件將保存四條 SADD 命令,如果使用AOF 重寫,那么AOF 文件中將只會保留下面一條命令:

1
sadd animals  "dog"  "tiger"  "panda"  "lion"  "cat"

  也就是說 AOF 文件重寫並不是對原文件進行重新整理,而是直接讀取服務器現有的鍵值對,然后用一條命令去代替之前記錄這個鍵值對的多條命令,生成一個新的文件后去替換原來的 AOF 文件。

   AOF 文件重寫觸發機制:通過 redis.conf 配置文件中的 auto-aof-rewrite-percentage:默認值為100,以及auto-aof-rewrite-min-size:64mb 配置,也就是說默認Redis會記錄上次重寫時的AOF大小,默認配置是當AOF文件大小是上次rewrite后大小的一倍且文件大於64M時觸發。

  這里再提一下,我們知道 Redis 是單線程工作,如果 重寫 AOF 需要比較長的時間,那么在重寫 AOF 期間,Redis將長時間無法處理其他的命令,這顯然是不能忍受的。Redis為了克服這個問題,解決辦法是將 AOF 重寫程序放到子程序中進行,這樣有兩個好處:

  ①、子進程進行 AOF 重寫期間,服務器進程(父進程)可以繼續處理其他命令。

  ②、子進程帶有父進程的數據副本,使用子進程而不是線程,可以在避免使用鎖的情況下,保證數據的安全性。

  使用子進程解決了上面的問題,但是新問題也產生了:因為子進程在進行 AOF 重寫期間,服務器進程依然在處理其它命令,這新的命令有可能也對數據庫進行了修改操作,使得當前數據庫狀態和重寫后的 AOF 文件狀態不一致。

  為了解決這個數據狀態不一致的問題,Redis 服務器設置了一個 AOF 重寫緩沖區,這個緩沖區是在創建子進程后開始使用,當Redis服務器執行一個寫命令之后,就會將這個寫命令也發送到 AOF 重寫緩沖區。當子進程完成 AOF 重寫之后,就會給父進程發送一個信號,父進程接收此信號后,就會調用函數將 AOF 重寫緩沖區的內容都寫到新的 AOF 文件中。

  這樣將 AOF 重寫對服務器造成的影響降到了最低。

6、AOF的優缺點

  優點:

  ①、AOF 持久化的方法提供了多種的同步頻率,即使使用默認的同步頻率每秒同步一次,Redis 最多也就丟失 1 秒的數據而已。

  ②、AOF 文件使用 Redis 命令追加的形式來構造,因此,即使 Redis 只能向 AOF 文件寫入命令的片斷,使用 redis-check-aof 工具也很容易修正 AOF 文件。

  ③、AOF 文件的格式可讀性較強,這也為使用者提供了更靈活的處理方式。例如,如果我們不小心錯用了 FLUSHALL 命令,在重寫還沒進行時,我們可以手工將最后的 FLUSHALL 命令去掉,然后再使用 AOF 來恢復數據。

  缺點:

  ①、對於具有相同數據的的 Redis,AOF 文件通常會比 RDF 文件體積更大。

  ②、雖然 AOF 提供了多種同步的頻率,默認情況下,每秒同步一次的頻率也具有較高的性能。但在 Redis 的負載較高時,RDB 比 AOF 具好更好的性能保證。

  ③、RDB 使用快照的形式來持久化整個 Redis 數據,而 AOF 只是將每次執行的命令追加到 AOF 文件中,因此從理論上說,RDB 比 AOF 方式更健壯。官方文檔也指出,AOF 的確也存在一些 BUG,這些 BUG 在 RDB 沒有存在。

   那么對於 AOF 和 RDB 兩種持久化方式,我們應該如何選擇呢?

  如果可以忍受一小段時間內數據的丟失,毫無疑問使用 RDB 是最好的,定時生成 RDB 快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快,而且使用 RDB 還可以避免 AOF 一些隱藏的 bug;否則就使用 AOF 重寫。但是一般情況下建議不要單獨使用某一種持久化機制,而是應該兩種一起用,在這種情況下,當redis重啟的時候會優先載入AOF文件來恢復原始的數據,因為在通常情況下AOF文件保存的數據集要比RDB文件保存的數據集要完整。Redis后期官方可能都有將兩種持久化方式整合為一種持久化模型。

7、RDB-AOF混合持久化

  這里補充一個知識點,在Redis4.0之后,既上一篇文章介紹的RDB和這篇文章介紹的AOF兩種持久化方式,又新增了RDB-AOF混合持久化方式。

  這種方式結合了RDB和AOF的優點,既能快速加載又能避免丟失過多的數據。

  具體配置為:

aof-use-rdb-preamble

  設置為yes表示開啟,設置為no表示禁用。

  當開啟混合持久化時,主進程先fork出子進程將現有內存副本全量以RDB方式寫入aof文件中,然后將緩沖區中的增量命令以AOF方式寫入aof文件中,寫入完成后通知主進程更新相關信息,並將新的含有 RDB和AOF兩種格式的aof文件替換舊的aof文件。

  簡單來說:混合持久化方式產生的文件一部分是RDB格式,一部分是AOF格式。

  這種方式優點我們很好理解,缺點就是不能兼容Redis4.0之前版本的備份文件了。

 

前面介紹Redis,我們都在一台服務器上進行操作的,也就是說讀和寫以及備份操作都是在一台Redis服務器上進行的,那么隨着項目訪問量的增加,對Redis服務器的操作也越加頻繁,雖然Redis讀寫速度都很快,但是一定程度上也會造成一定的延時,那么為了解決訪問量大的問題,通常會采取的一種方式是主從架構Master/Slave,Master 以寫為主,Slave 以讀為主,Master 主節點更新后根據配置,自動同步到從機Slave 節點。

  接下來我們就來介紹如何進行主從架構的搭建。

  ps:這里我是在一台機器上模擬多個Redis服務器,與實際生產環境中相比,基本配置都是一樣,僅僅是IP地址和端口號變化。

  

 

1、修改配置文件

  首先將redis.conf 配置文件復制三份,通過修改端口分別模擬三台Redis服務器。

  

  然后我們分別對這三個redis.conf 文件進行修改。

  ①、修改 daemonize yes

  

  表示指定Redis以守護進程的方式啟動(后台啟動)

  ②、配置PID文件路徑 pidfile

  

  表示當redis作為守護進程運行的時候,它會把 pid 默認寫到 /var/redis/run/redis_6379.pid 文件里面

  ③、配置端口 port

  

  ④、配置log 文件名字

  

  ⑤、配置rdb文件名

  

  依次將 6380redis.conf 、6381redis.conf 配置一次,則配置完畢。

  接下來我們分別啟動這三個服務。

  

  通過命令查看Redis是否啟動:

  

  接下來通過如下命令分別進入到這三個Redis客戶端:

1
2
3
redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381

  注意:如果修改端口了,啟動redis-cli 命令,比如加上 -p 端口,否則連接不上.如果密碼也修改了,則還得添加密碼 -a 密碼指令來連接.

2、設置主從關系

  ①、通過  info replication 命令查看節點角色

      

  

  我們發現這三個節點都是扮演的 Master 角色。那么如何將 6380 和 6381 節點變為 Slave 角色呢?

  ②、選擇6380端口和6381端口,執行命令:SLAVEOF 127.0.0.1 6379

      

  我們再看 6379 節點信息:

  

  這里通過命令來設置主從關系,一旦服務重啟,那么角色關系將不復存在。想要永久的保存這種關系,可以通過配置redis.conf 文件來配置。

1
slaveof 127.0.0.1 6379

3、測試主從關系

  ①、增量復制

  主節點執行 set k1 v1 命令,從節點 get k1 能獲取嗎?

  

  

  

  由上圖可知是可以獲取的。

  ②、全量復制

  通過執行 SLAVEOF 127.0.0.1 6379,如果主節點 6379 以前還存在一些 key,那么執行命令之后,從節點會將以前的信息也都復制過來嗎?

  答案也是肯定的,這里我就不貼測試結果了。

  ③、主從讀寫分離

  主節點能夠執行寫命令,從節點能夠執行寫命令嗎?

  

  這里的原因是在配置文件 6381redis.conf 中對於 slave-read-only 的配置

  

  如果我們將其修改為 no 之后,執行寫命令是可以的。

  

  但是從節點寫命令的數據從節點或者主節點都不能獲取的。

  ④、主節點宕機

  主節點 Maste 掛掉,兩個從節點角色會發生變化嗎?

  

  

  上圖可知主節點 Master 掛掉之后,從節點角色還是不會改變的。

  ⑤、主節點宕機后恢復

  主節點Master掛掉之后,馬上啟動主機Maste,主節點扮演的角色還是 Master 嗎?

  

  也就是說主節點掛掉之后重啟,又恢復了主節點的角色。

4、哨兵模式

  通過前面的配置,主節點Master 只有一個,一旦主節點掛掉之后,從節點沒法擔起主節點的任務,那么整個系統也無法運行。如果主節點掛掉之后,從節點能夠自動變成主節點,那么問題就解決了,於是哨兵模式誕生了。

  哨兵模式就是不時地監控redis是否按照預期良好地運行(至少是保證主節點是存在的),若一台主機出現問題時,哨兵會自動將該主機下的某一個從機設置為新的主機,並讓其他從機和新主機建立主從關系。

  

 

  哨兵模式搭建步驟:

  ①、在配置文件目錄下新建 sentinel.conf 文件,名字絕不能錯,然后配置相應內容

   

1
sentinel monitor 被監控機器的名字(自己起名字) ip地址 端口號 得票數

  

  分別配置被監控的名字,ip地址,端口號,以及得票數。上面的得票數為1表示表示主機掛掉后salve投票看讓誰接替成為主機,得票數大於1便成為主機

  ②、啟動哨兵

1
redis-sentinel /etc/redis/sentinel.conf

  啟動界面:

  

  接下來,我們干掉主機 6379,然后看從節點有啥變化。

  

  干掉主節點之后,我們查看后台打印日志,發現 6381投票變為主節點了。

  

  這時候我們查看從節點 6381的節點信息:

  

  6381 節點自動變為主節點了。

  PS:哨兵模式也存在單點故障問題,如果哨兵機器掛了,那么就無法進行監控了,解決辦法是哨兵也建立集群,Redis哨兵模式是支持集群的。

5、主從復制原理

  Redis的復制功能分為同步(sync)和命令傳播(command propagate)兩個操作。

  ①、舊版同步

  當從節點發出 SLAVEOF 命令,要求從服務器復制主服務器時,從服務器通過向主服務器發送 SYNC 命令來完成。該命令執行步驟:

  1、從服務器向主服務器發送 SYNC 命令

  2、收到 SYNC 命令的主服務器執行 BGSAVE 命令,在后台生成一個 RDB 文件,並使用一個緩沖區記錄從開始執行的所有寫命令

  3、當主服務器的 BGSAVE 命令執行完畢時,主服務器會將 BGSAVE 命令生成的 RDB 文件發送給從服務器,從服務器接收此 RDB 文件,並將服務器狀態更新為RDB文件記錄的狀態。

  4、主服務器將緩沖區的所有寫命令也發送給從服務器,從服務器執行相應命令。

  ②、命令傳播

  當同步操作完成之后,主服務器會進行相應的修改命令,這時候從服務器和主服務器狀態就會不一致。

  為了讓主服務器和從服務器保持狀態一致,主服務器需要對從服務器執行命令傳播操作,主服務器會將自己的寫命令發送給從服務器執行。從服務器執行相應的命令之后,主從服務器狀態繼續保持一致。

  總結:通過同步操作以及命令傳播功能,能夠很好的保證了主從一致的特性。

  但是我們考慮一個問題,如果從服務器在同步主服務器期間,突然斷開了連接,而這時候主服務器進行了一些寫操作,這時候從服務器恢復連接,如果我們在進行同步,那么就必須將主服務器從新生成一個RDB文件,然后給從服務器加載,這樣雖然能夠保證一致性,但是其實斷開連接之前主從服務器狀態是保持一致的,不一致的是從服務器斷開連接,而主服務器執行了一些寫命令,那么從服務器恢復連接后能不能只要斷開連接的哪些寫命令,而不是整個RDB快照呢?

  同步操作其實是一個非常耗時的操作,主服務器需要先通過 BGSAVE 命令來生成一個 RDB 文件,然后需要將該文件發送給從服務器,從服務器接收該文件之后,接着加載該文件,並且加載期間,從服務器是無法處理其他命令的。

  為了解決這個問題,Redis從2.8版本之后,使用了新的同步命令 PSYNC 來代替 SYNC 命令。該命令的部分重同步功能用於處理斷線后重復制的效率問題。也就是說當從服務器在斷線后重新連接主服務器時,主服務器只將斷開連接后執行的寫命令發送給從服務器,從服務器只需要接收並執行這些寫命令即可保持主從一致。

6、主從復制的缺點

  主從復制雖然解決了主節點的單點故障問題,但是由於所有的寫操作都是在 Master 節點上操作,然后同步到 Slave 節點,那么同步就會有一定的延時,當系統很繁忙的時候,延時問題就會更加嚴重,而且會隨着從節點slave的增多而愈加嚴重。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM