就publish/subscribe功能看redis集群模式下的隊列技術(一)


Redis 簡介

Redis 是完全開源免費的,是一個高性能的key-value數據庫。

Redis 與其他 key - value 緩存產品有以下三個特點:

Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用。

Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。

Redis支持數據的備份,即master-slave模式的數據備份。

性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s。

Redis的安裝

 

wget http://download.redis.io/releases/redis-3.2.4.tar.gz

tar –zxvf redis-stable.tar.gz 解壓

make 編譯

可能出現問題make[3]: gcc: Command not found,未安裝gcc編譯工具

編譯成功后,進入src文件夾,執行make install進行Redis安裝

make install  --> /usr/local/bin目錄下有:redis-server,redis-cli,redis-check-aof,redis-check-dump

redis-server –v   檢查是否安裝成功

啟動redis,進入到redis.conf目錄,執行

redis-server redis.conf.  如果后面沒有跟redis.conf則按照默認配置啟動

redis配置文件

         redis.conf 配置項說明如下:

1. Redis默認不是以守護進程的方式運行,可以通過該配置項修改,使用yes啟用守護進程

    daemonize yes

2. 當Redis以守護進程方式運行時,Redis默認會把pid寫入/var/run/redis.pid文件,可以通過pidfile指定

    pidfile /var/run/redis.pid

3. 指定Redis監聽端口,默認端口為6379,作者在自己的一篇博文中解釋了為什么選用6379作為默認端口,因為6379在手機按鍵上MERZ對應的號碼,而MERZ取自意大利歌女Alessia Merz的名字

    port 6379

4. 綁定的主機地址

    bind 127.0.0.1   這個Ip要設置成你服務器的Ip

5.當 客戶端閑置多長時間后關閉連接,如果指定為0,表示關閉該功能

    timeout 300

6. 指定日志記錄級別,Redis總共支持四個級別:debug、verbose、notice、warning,默認為verbose

    loglevel verbose

7. 日志記錄方式,默認為標准輸出,如果配置Redis為守護進程方式運行,而這里又配置為日志記錄方式為標准輸出,則日志將會發送給/dev/null

    logfile stdout

8. 設置數據庫的數量,默認數據庫為0,可以使用SELECT <dbid>命令在連接上指定數據庫id

    databases 16

9. 指定在多長時間內,有多少次更新操作,就將數據同步到數據文件,可以多個條件配合

    save <seconds> <changes>

    Redis默認配置文件中提供了三個條件:

    save 900 1

    save 300 10

    save 60 10000

    分別表示900秒(15分鍾)內有1個更改,300秒(5分鍾)內有10個更改以及60秒內有10000個更改。

 

10. 指定存儲至本地數據庫時是否壓縮數據,默認為yes,Redis采用LZF壓縮,如果為了節省CPU時間,可以關閉該選項,但會導致數據庫文件變的巨大

    rdbcompression yes

11. 指定本地數據庫文件名,默認值為dump.rdb

    dbfilename dump.rdb

12. 指定本地數據庫存放目錄

    dir ./

13. 設置當本機為slav服務時,設置master服務的IP地址及端口,在Redis啟動時,它會自動從master進行數據同步

    slaveof <masterip> <masterport>

14. 當master服務設置了密碼保護時,slav服務連接master的密碼

    masterauth <master-password>

15. 設置Redis連接密碼,如果配置了連接密碼,客戶端在連接Redis時需要通過AUTH <password>命令提供密碼,默認關閉

    requirepass foobared

16. 設置同一時間最大客戶端連接數,默認無限制,Redis可以同時打開的客戶端連接數為Redis進程可以打開的最大文件描述符數,如果設置 maxclients 0,表示不作限制。當客戶端連接數到達限制時,Redis會關閉新的連接並向客戶端返回max number of clients reached錯誤信息

    maxclients 128

17. 指定Redis最大內存限制,Redis在啟動時會把數據加載到內存中,達到最大內存后,Redis會先嘗試清除已到期或即將到期的Key,當此方法處理 后,仍然到達最大內存設置,將無法再進行寫入操作,但仍然可以進行讀取操作。Redis新的vm機制,會把Key存放內存,Value會存放在swap區

    maxmemory <bytes>

18. 指定是否在每次更新操作后進行日志記錄,Redis在默認情況下是異步的把數據寫入磁盤,如果不開啟,可能會在斷電時導致一段時間內的數據丟失。因為 redis本身同步數據文件是按上面save條件來同步的,所以有的數據會在一段時間內只存在於內存中。默認為no

    appendonly no

19. 指定更新日志文件名,默認為appendonly.aof

     appendfilename appendonly.aof

20. 指定更新日志條件,共有3個可選值: 
    no:表示等操作系統進行數據緩存同步到磁盤(快) 
    always:表示每次更新操作后手動調用fsync()將數據寫到磁盤(慢,安全) 
    everysec:表示每秒同步一次(折衷,默認值)

    appendfsync everysec

 

21. 指定是否啟用虛擬內存機制,默認值為no,簡單的介紹一下,VM機制將數據分頁存放,由Redis將訪問量較少的頁即冷數據swap到磁盤上,訪問多的頁面由磁盤自動換出到內存中(在后面的文章我會仔細分析Redis的VM機制)

     vm-enabled no

22. 虛擬內存文件路徑,默認值為/tmp/redis.swap,不可多個Redis實例共享

     vm-swap-file /tmp/redis.swap

23. 將所有大於vm-max-memory的數據存入虛擬內存,無論vm-max-memory設置多小,所有索引數據都是內存存儲的(Redis的索引數據 就是keys),也就是說,當vm-max-memory設置為0的時候,其實是所有value都存在於磁盤。默認值為0

     vm-max-memory 0

24. Redis swap文件分成了很多的page,一個對象可以保存在多個page上面,但一個page上不能被多個對象共享,vm-page-size是要根據存儲的 數據大小來設定的,作者建議如果存儲很多小對象,page大小最好設置為32或者64bytes;如果存儲很大大對象,則可以使用更大的page,如果不 確定,就使用默認值

     vm-page-size 32

25. 設置swap文件中的page數量,由於頁表(一種表示頁面空閑或使用的bitmap)是在放在內存中的,,在磁盤上每8個pages將消耗1byte的內存。

     vm-pages 134217728

26. 設置訪問swap文件的線程數,最好不要超過機器的核數,如果設置為0,那么所有對swap文件的操作都是串行的,可能會造成比較長時間的延遲。默認值為4

     vm-max-threads 4

27. 設置在向客戶端應答時,是否把較小的包合並為一個包發送,默認為開啟

    glueoutputbuf yes

28. 指定在超過一定的數量或者最大的元素超過某一臨界值時,采用一種特殊的哈希算法

    hash-max-zipmap-entries 64

    hash-max-zipmap-value 512

29. 指定是否激活重置哈希,默認為開啟(后面在介紹Redis的哈希算法時具體介紹)

    activerehashing yes

30. 指定包含其它的配置文件,可以在同一主機上多個Redis實例之間使用同一份配置文件,而同時各個實例又擁有自己的特定配置文件

    include /path/to/local.conf

redis數據類型

         Redis支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

String:

         Get、set。注意:一個鍵最大能存儲512MB。

Hash:

            Hmset、hmget、hkeys、hvals

List:

            Lpush、lrange

Set

         sadd、smembers

zset

         ZADD 集合名  序號  集合元素

zadd myZSet 1 zlh

zadd mySet 2 Tom 3 Jim

zcard myZSet  查看zset集合的成員個數

zrange mZySet 0 -1

zrange mZySet 0 -1 withscores

zrank mZySet Jim  獲取zset成員的下標位置

zcount mySet 1 3 

zrem myZSet zlh  刪除指定的一個成員或多個成員

zscore myZset zlh

zincrby myZset 4 tom  tom的分數值加4

zrangebyscore myZset  1 5

Redis 發布訂閱

         Redis 發布訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。

 

subscribe dongnao  客戶端訂閱消息,dongnao為相應的頻道

publish dongnao message  發布消息,同時訂閱該頻道的客戶端能收到該消息

Redis 事務

         Redis 事務可以一次執行多個命令, 並且帶有以下兩個重要的保證:

事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執行。事務在執行的過程中,不會被其他客戶端發送來的命令請求所打斷。

事務是一個原子操作:事務中的命令要么全部被執行,要么全部都不執行。

一個事務從開始到執行會經歷以下三個階段:

開始事務。

命令入隊。

執行事務。

 

MULTI  開始一個事物

Set dongnao jack

Get dongnao

Hmset  map key1 value1 key2 value2

Hmget map key1

Exec 執行事物

Redis 數據備份與恢復

默認情況下 每隔一段時間redis服務器程序會自動對數據庫做一次遍歷,把內存快照寫在一個叫做“dump.rdb”的文件里,這個持久化機制叫做SNAPSHOT。有了SNAPSHOT后,如果服務器宕機,重新啟動redis服務器程序時redis會自動加載dump.rdb,將數據庫狀態恢復到上一次做SNAPSHOT時的狀態。

手動進行內存備份:

Save

Redis 安全

         config get requirepass  獲取密碼

         config set requirepass 123

         config get requirepass

auth password 密碼驗證

redis持久化

Snapshotting快照持久化

         RDB

 快照是默認的持久化方式。這種方式是就是將內存中數據以快照的方式寫入到二進制文件中,默認的文件名為dump.rdb。可以通過配置設置自動做快照持久化的方式。我們可以配置redis在n秒內如果超過m個key被修改就自動做快照,下面是默認的快照保存配置:

save 900 1  #900秒內如果超過1個key被修改,則發起快照保存
save 300 10 #300秒內容如超過10個key被修改,則發起快照保存
save 60 10000

client 也可以使用save或者bgsave命令通知redis做一次快照持久化,每次快照持久化都是將內存數據完整寫入到磁盤一次,並不是增量的只同步臟數據。如果數據量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴重影響性能。另外由於快照方式是在一定間隔時間做一次的,所以如果redis意外down掉的話,就會丟失最后一次快照后的所有修改。

Append-only

AOF

redis會將每一個收到的寫命令都通過write函數追加到文件中(默認是appendonly.aof)。當redis重啟時會通過重新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。

appendonly yes           #啟用aof持久化方式
# appendfsync always   #每次收到寫命令就立即強制寫入磁盤,最慢的,但是保證完全的持久化,不推薦使用
appendfsync everysec     #每秒鍾強制寫入磁盤一次,在性能和持久化方面做了很好的折中,推薦
# appendfsync no    #完全依賴os,性能最好,持久化沒保證

redis主從

         redis主從復制過程: 當配置好slave后,slave與master建立連接,然后發送sync命令。無論是第一次連接還是重新連接,master都會啟動一個后台進程,將 數據庫快照保存到文件中,同時master主進程會開始收集新的寫命令並緩存。后台進程完成寫文件后,master就發送文件給slave,slave將 文件保存到硬盤上,再加載到內存中,接着master就會把緩存的命令轉發給slave,后續master將收到的寫命令發送給slave。如果master同時收到多個slave發來的同步連接命令,master只會啟動一個進程來寫數據庫鏡像,然后發送給所有的slave。master同步數據時是非阻塞式的,可以接收用戶的讀寫請求。然而在slave端是阻塞模式的,slave在同步master數據時,並不能夠響應客戶端的查詢。

可以在master禁用數據持久化,只需要注釋掉master 配置文件中的所有save配置,然后只在slave上配置數據持久化

Redis集群

    Redis 集群中內置了 16384 個哈希槽,當需要在 Redis 集群中放置一個 key-value時,redis 先對 key 使用 crc16 算法算出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大致均等的將哈希槽映射到不同的節點。集群的每個節點負責一部分hash槽。這種結構很容易添加或者刪除節點,並且無論是添加刪除或者修改某一個節點,都不會造成集群不可用的狀態。使用哈希槽的好處就在於可以方便的添加或移除節點。當需要增加節點時,只需要把其他節點的某些哈希槽挪到新節點就可以了;當需要移除節點時,只需要把移除節點上的哈希槽挪到其他節點就行了;在這一點上,我們以后新增或移除節點的時候不用先停掉所有的 redis 服務。Hash slots

         基於centos的集群

         1、集群至少要有3個節點,每個節點都有主從結構

                  新建三個文件夾,把配置文件cp進去,然后修改配置文件端口,把支持集群配置放開,啟動該節點

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

         2、安裝ruby,必須2.0以上,2.0以上自帶rubygems包管理器

         yum install ruby

         3、gem命令安裝redis包,增加redis-trib.rb調用redis的接口包

         gem install redis

         4、用redis-trib.rb集群工具管理redis集群

         ./redis-trib.rb  create --replicas 1 120.77.22.187:7000 120.77.22.187:8000 120.77.22.187:9000 120.77.22.187:7010 120.77.22.187:8010 120.77.22.187:9010

         --replicas 1 設置從節點個數

         進入集群模式去操作redis命令,-c集群模式

         redis-cli -c  -h –p

 

 

redis集群添加節點

主要是看現象,slots轉移時,對應數據會有什么變化?

增加節點

./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000

查看節點情況

cluster nodes

移動哈希槽,哈希槽重新分配

./redis-trib.rb reshard 127.0.0.1:7000

輸入all 表示從所有的主節點中隨機轉移,湊夠xx個哈希槽

Redis集群刪除節點

把hash slots轉出來,轉到其他master節點上

./redis-trib.rb reshard 127.0.0.1:7000

然后刪除節點

./redis-trib.rb del-node 120.77.22.187:9020 94ee1415a16076f4070c5dd4b94defc14618dbb8

Redis-sentinel高可用

         Redis-Sentinel是Redis官方推薦的高可用性(HA)解決方案,當用Redis做Master-slave的高可用方案時,假如master宕機了,Redis本身(包括它的很多客戶端)都沒有實現自動進行主備切換,而Redis-sentinel本身也是一個獨立運行的進程,它能監控多個master-slave集群,發現master宕機后能進行自動切換。

它的主要功能有以下幾點

不時地監控redis是否按照預期良好地運行;

如果發現某個redis節點運行出現狀況,能夠通知另外一個進程(例如它的客戶端);

能夠進行自動切換。當一個master節點不可用時,能夠選舉出master的多個slave(如果有超過一個slave的話)中的一個來作為新的master,其它的slave節點會將它所追隨的master的地址改為被提升為master的slave的新地址。

需要注意的是,配置文件在sentinel運行期間是會被動態修改的,例如當發生主備切換時候,配置文件中的master會被修改為另外一個slave。這樣,之后sentinel如果重啟時,就可以根據這個配置來恢復其之前所監控的redis集群的狀態。

sentinel monitor mymaster 127.0.0.1 6379 1
sentinel down-after-milliseconds mymaster 60000
#sentinel can-failover mymaster yes
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

當sentinel集群式,解決這個問題的方法就變得很簡單,只需要多個sentinel互相溝通來確認某個master是否真的死了,這個2代表,當集群中有2個sentinel認為master死了時,才能真正認為該master已經不可用了。

down-after-milliseconds
sentinel會向master發送心跳PING來確認master是否存活,如果master在“一定時間范圍”內不回應PONG 或者是回復了一個錯誤消息,那么這個sentinel會主觀地(單方面地)認為這個master已經不可用了(subjectively down, 也簡稱為SDOWN)。而這個down-after-milliseconds就是用來指定這個“一定時間范圍”的,單位是毫秒。

can-failover

no 表示當前sentinel是一個觀察者,只參與投票不參與實施failover

全局中至少有一個是yes

parallel-syncs

當新master產生時,同時進行“slaveof”到新master並進行“SYNC”的slave個數

默認為1,建議保持默認值  

在salve執行salveof與同步時,將會終止客戶端請求
failover-timeout

failover過期時間,當failover開始后,在此時間內仍然沒有觸發任何failover操作

當前sentinel將會認為此次failoer失敗


免責聲明!

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



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