緩存-redis 三種模式搭建和運行原理

標(biāo)簽: redis 緩存 主從 哨兵 集群


本文簡單的介紹redis三種模式在linux的安裝部署和數(shù)據(jù)存儲的總結(jié),希望可以相互交流相互提升。

一. redis安裝

1、安裝單機版redis

對于Centos7在安裝redis之前需要進行一些常用工具的安裝:

sudo yum install net-tools 網(wǎng)絡(luò)工具,比如ifconfig
sudo yum -y install lrzsz 文件的上傳下載

關(guān)閉防火墻

systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall開機啟動
firewall-cmd --state #查看默認(rèn)防火墻狀態(tài)(關(guān)閉后顯示notrunning,開啟后顯示running)

正式安裝redis

使用命令的模式進行redis的安裝(文件down到/usr/local/sftp/
安裝前需要進行tcl的安裝,否則在make的時候報錯
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
tar -zxvf tcl8.6.1-src.tar.gz
cd /usr/local/tcl8.6.1/unix/
./configure
make && make install

使用redis-3.2.8.tar.gz(截止2017年4月的最新穩(wěn)定版)
tar -zxvf redis-3.2.8.tar.gz
cd redis-3.2.8
make && make test && make install

2. redis 的make test出現(xiàn)異常解決

在redis進行maketest時候會出現(xiàn)一系列的異常,有如下解決方案:

  • You need tcl 8.5 or newer in order to run the Redis test
    解決方案:前面已經(jīng)安裝了tcl;
  • [exception]: Executing test client: NOREPLICAS Not enough good slaves to write..
    NOREPLICAS Not enough good slaves to write.
    解決方案:vim tests/integration/replication-2.tcl
    將其中的第一個if里面的after 1000修改成after 10000,延長測試時間
  • [err]: Slave should be able to synchronize with the master in tests/integration/replication-psync.tcl
    Replication not started.
    解決方案:重新make test一次就好了;
  • [err]: Test replication partial resync: ok psync (diskless: yes, reconnect: 1) in tests/integration/replication-psync.tcl
    解決方案:vim tests/integration/replication-psync.tcl
    將其中的after 100修改成after 1000就好了。

3. redis的生產(chǎn)環(huán)境啟動方案

用redis-server啟動一下redis,做一些實驗沒什么意義。

要把redis作為一個系統(tǒng)的daemon進程去運行的,每次系統(tǒng)啟動,redis進程一起啟動,操作不走如下:

  1. redis utils目錄下,有個redis_init_script腳本
  1. 將redis_init_script腳本拷貝到linux的/etc/init.d目錄中,將redis_init_script重命名為redis_6379,6379是我們希望這個redis實例監(jiān)聽的端口號
  2. 修改redis_6379腳本的第6行的REDISPORT,設(shè)置為相同的端口號(默認(rèn)就是6379)
  3. 創(chuàng)建兩個目錄:/etc/redis(存放redis的配置文件),/var/redis/6379(存放redis的持久化文件)
  4. 修改redis配置文件(默認(rèn)在根目錄下,redis.conf),拷貝到/etc/redis目錄中,修改名稱為6379.conf
  5. 修改redis.conf中的部分配置為生產(chǎn)環(huán)境
    daemonize yes        讓redis以daemon進程運行
    pidfile /var/run/redis_6379.pid 設(shè)置redis的pid文件位置
    port 6379          設(shè)置redis的監(jiān)聽端口號
    dir /var/redis/6379     設(shè)置持久化文件的存儲位置
  6. 啟動redis,執(zhí)行cd /etc/init.d, chmod 777 redis_6379,./redis_6379 start
  7. 確認(rèn)redis進程是否啟動,ps -ef | grep redis
    9.讓redis跟隨系統(tǒng)啟動自動啟動 sudo update-rc.d reds_6379 defaults(7 無法執(zhí)行 可以使用下面的方式)
    在redis_6379腳本中,最上面,加入兩行注釋
      # chkconfig: 2345 90 10
      # description: Redis is a persistent key-value database
    chkconfig redis_6379 on

4. redis cli的使用

redis-cli SHUTDOWN,連接本機的6379端口停止redis進程
redis-cli -h 127.0.0.1 -p 6379 SHUTDOWN,制定要連接的ip和端口號
redis-cli PING,ping redis的端口,看是否正常
redis-cli,進入交互式命令行

二. redis 之 RDB 和 AOF

RDB和AOF是redis的一種數(shù)據(jù)持久化的機制。持久化是為了避免系統(tǒng)在發(fā)生災(zāi)難性的系統(tǒng)故障時導(dǎo)致的系統(tǒng)數(shù)據(jù)丟失。我們一般會將數(shù)據(jù)存放在本地磁盤,還會定期的將數(shù)據(jù)上傳到云服務(wù)器。
  RDB 是redis的snapshotting,通過redis.conf中的save配置進行設(shè)置,如 save 60 1000:

表示每隔60s,如果有超過1000個key發(fā)生了變更,那么就生成一個新的dump.rdb文件,就是當(dāng)前redis內(nèi)存中完整的數(shù)據(jù)快照,這個操作也被稱之為snapshotting,也可以手動調(diào)用save或者bgsave命令,同步或異步執(zhí)行rdb快照生成

AOF 是以appendonly方式進行數(shù)據(jù)的儲存的,開啟AOF模式后,所有存進redis內(nèi)存的數(shù)據(jù)都會進入os cache中,然后默認(rèn)1秒執(zhí)行一次fsync寫入追加到appendonly.aof文件中。一般我們配置redis.conf中的一下指令:

appendonly yes 可以打開AOF持久化機制,在生產(chǎn)環(huán)境里面,一般來說AOF都是要打開的;
appendfsync everysec 每秒將os cache中的數(shù)據(jù)fsync到磁盤,這個最常用的,生產(chǎn)環(huán)境一般都這么配置,性能很高,QPS可以上萬;還有另外兩種參數(shù)always和no,前者持續(xù)寫入,性能低,數(shù)據(jù)保存完整,后者os cache自己控制寫入時間,那樣可能丟失數(shù)據(jù)很多;
rewrite策略
  auto-aof-rewrite-percentage 100
  auto-aof-rewrite-min-size 64mb
  表示在第一次將緩存中的數(shù)據(jù)追加到aof文件中后記錄次文件的大小,比如128MB,在追加數(shù)據(jù)到文件大小是上次文件的100%,也就是2倍,此時需要判斷文件是否大于64mb,大于min-size則進行rewrite。

AOF和RDB模式我們一般在生產(chǎn)環(huán)境都會打開,一般而言,redis服務(wù)掛掉后進行重啟會優(yōu)先家在aof中的文件。

三. redis 之 主從配置

1. 主從架構(gòu)的核心原理

當(dāng)啟動一個slave node的時候,它會發(fā)送一個PSYNC命令給master node,如果這是slave node重新連接master node,那么master node僅僅會復(fù)制給slave部分缺少的數(shù)據(jù);否則如果是slave node第一次連接master node,那么會觸發(fā)一次full resynchronization;
  開始full resynchronization的時候,master會啟動一個后臺線程,開始生成一份RDB快照文件,同時還會將從客戶端收到的所有寫命令緩存在內(nèi)存中。RDB文件生成完畢之后,master會將這個RDB發(fā)送給slave,slave會先寫入本地磁盤,然后再從本地磁盤加載到內(nèi)存中。然后master會將內(nèi)存中緩存的寫命令發(fā)送給slave,slave也會同步這些數(shù)據(jù)。
  slave node如果跟master node有網(wǎng)絡(luò)故障,斷開了連接,會自動重連。master如果發(fā)現(xiàn)有多個slave node都來重新連接,僅僅會啟動一個rdb save操作,用一份數(shù)據(jù)服務(wù)所有slave node。

2. 主從復(fù)制的斷點續(xù)傳

從redis 2.8開始,就支持主從復(fù)制的斷點續(xù)傳,如果主從復(fù)制過程中,網(wǎng)絡(luò)連接斷掉了,那么可以接著上次復(fù)制的地方,繼續(xù)復(fù)制下去,而不是從頭開始復(fù)制一份。

master node會在內(nèi)存中常見一個backlog,master和slave都會保存一個replica offset還有一個master id,offset就是保存在backlog中的。如果master和slave網(wǎng)絡(luò)連接斷掉了,slave會讓master從上次的replica offset開始繼續(xù)復(fù)制,但是如果沒有找到對應(yīng)的offset,那么就會執(zhí)行一次resynchronization。

3. 無磁盤化復(fù)制

master在內(nèi)存中直接創(chuàng)建rdb,然后發(fā)送給slave,不會在自己本地落地磁盤了,可以有如下配置:

repl-diskless-sync
repl-diskless-sync-delay 等待一定時長再開始復(fù)制,因為要等更多slave重新連接過來

4. 過期key處理

slave不會過期key,只會等待master過期key。如果master過期了一個key,或者通過LRU淘汰了一個key,那么會模擬一條del命令發(fā)送給slave。

5. 主從架構(gòu)redis配置

  1. 打開slaveof參數(shù)
      在slave node上配置:slaveof masterip masterport
  1. redis slave node只讀,默認(rèn)開啟,slave-read-only
  2. master上啟用安全認(rèn)證,requirepass (master 配置)
    slave連接master口令,masterauth(slave node 配置)

四. redis 之哨兵模式

1. 哨兵主要功能

  • 集群監(jiān)控,負(fù)責(zé)監(jiān)控redis master和slave進程是否正常工作
  • 消息通知,如果某個redis實例有故障,那么哨兵負(fù)責(zé)發(fā)送消息作為報警通知給管理員
  • 故障轉(zhuǎn)移,如果master node掛掉了,會自動轉(zhuǎn)移到slave node上
  • 配置中心,如果故障轉(zhuǎn)移發(fā)生了,通知client客戶端新的master地址

2. reids 對于異步復(fù)制和腦裂數(shù)據(jù)丟失問題解決

min-slaves-to-write 3
min-slaves-max-lag 10

在redis.conf配置文件中,上面的參數(shù)代表至少需要3個slaves節(jié)點與master節(jié)點進行連接,并且master和每個slave的數(shù)據(jù)同步延遲不能超過10秒。一旦上面的設(shè)定沒有匹配上,則master不在提供相應(yīng)的服務(wù)。

3. 哨兵模式的核心機制

  • 3.1 sdown和odown轉(zhuǎn)換機制

sdown和odown兩種失敗狀態(tài):

  • sdown是主觀宕機,就一個哨兵如果自己覺得一個master宕機了,那么就是主觀宕機;
  • odown是客觀宕機,如果quorum數(shù)量的哨兵都覺得一個master宕機了,那么就是客觀宕機;

sdown達(dá)成的條件很簡單,如果一個哨兵ping一個master,超過了is-master-down-after-milliseconds指定的毫秒數(shù)之后,就主觀認(rèn)為master宕機
  sdown到odown轉(zhuǎn)換的條件很簡單,如果一個哨兵在指定時間內(nèi),收到了quorum指定數(shù)量的其他哨兵也認(rèn)為那個master是sdown了,那么就認(rèn)為是odown了,客觀認(rèn)為master宕機

  • 3.2 哨兵集群的自動發(fā)現(xiàn)機制

哨兵互相之間的發(fā)現(xiàn),是通過redis的pub/sub系統(tǒng)實現(xiàn)的,每個哨兵都會往sentinel:hello這個channel里發(fā)送一個消息,這時候所有其他哨兵都可以消費到這個消息,并感知到其他的哨兵的存在。
  每隔兩秒鐘,每個哨兵都會往自己監(jiān)控的某個master+slaves對應(yīng)的sentinel:hello channel里發(fā)送一個消息,內(nèi)容是自己的host、ip和runid還有對這個master的監(jiān)控配置。
  每個哨兵也會去監(jiān)聽自己監(jiān)控的每個master+slaves對應(yīng)的sentinel:hello channel,然后去感知到同樣在監(jiān)聽這個master+slaves的其他哨兵的存在。
  每個哨兵還會跟其他哨兵交換對master的監(jiān)控配置,互相進行監(jiān)控配置的同步。

  • 3.3 slave配置的自動糾正
      哨兵會負(fù)責(zé)自動糾正slave的一些配置,比如slave如果要成為潛在的master候選人,哨兵會確保slave在復(fù)制現(xiàn)有master的數(shù)據(jù);如果slave連接到了一個錯誤的master上,比如故障轉(zhuǎn)移之后,那么哨兵會確保它們連接到正確的master上。

  • 3.4 slave->master選舉算法
      如果一個master被認(rèn)為odown了,而且majority哨兵都允許了主備切換,那么某個哨兵就會執(zhí)行主備切換操作,此時首先要選舉一個slave來作為新的master。

選舉會考慮slave的一些信息

  1. 跟master斷開連接的時長
  2. slave優(yōu)先級
  3. 復(fù)制offset
  4. run id

如果一個slave跟master斷開連接已經(jīng)超過了down-after-milliseconds的10倍,外加master宕機的時長,那么slave就被認(rèn)為不適合選舉為master
  
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

接下來會對slave進行排序

  1. 按照slave優(yōu)先級進行排序,slave priority越低,優(yōu)先級就越高
  2. 如果slave priority相同,那么看replica offset,哪個slave復(fù)制了越多的數(shù)據(jù),offset越靠后,優(yōu)先級就越高
  3. 如果上面兩個條件都相同,那么選擇一個run id比較小的那個slave
  • 3.5 quorum和majority

每次一個哨兵要做主備切換,首先需要quorum數(shù)量的哨兵認(rèn)為odown,然后選舉出一個slave來做切換,這個slave還得得到majority哨兵的授權(quán),才能正式執(zhí)行切換;

如果quorum < majority,比如5個哨兵,majority就是3,quorum設(shè)置為2,那么就3個哨兵授權(quán)就可以執(zhí)行切換;
  但是如果quorum >= majority,那么必須quorum數(shù)量的哨兵都授權(quán),比如5個哨兵,quorum是5,那么必須5個哨兵都同意授權(quán),才能執(zhí)行切換

  • 3.6 configuration epoch

哨兵會對一套redis master+slave進行監(jiān)控,有相應(yīng)的監(jiān)控的配置,執(zhí)行切換的那個哨兵,會從要切換到的新master(salve->master)那里得到一個configuration epoch,這就是一個version號,每次切換的version號都必須是唯一的.
  如果第一個選舉出的哨兵切換失敗了,那么其他哨兵,會等待failover-timeout時間,然后接替繼續(xù)執(zhí)行切換,此時會重新獲取一個新的configuration epoch,作為新的version號。

  • 3.7 configuraiton傳播

哨兵完成切換之后,會在自己本地更新生成最新的master配置,然后同步給其他的哨兵,就是通過之前說的pub/sub消息機制
  這里之前的version號就很重要了,因為各種消息都是通過一個channel去發(fā)布和監(jiān)聽的,所以一個哨兵完成一次新的切換之后,新的master配置是跟著新的version號的,其他的哨兵都是根據(jù)版本號的大小來更新自己的master配置的。

4. 經(jīng)典的三哨兵集群搭建

  • 4.1 修改sentinel.conf配置文件如下參數(shù):
  1. 創(chuàng)建如下文件夾
    mkdir /etc/sentinal
    mkdir -p /var/sentinal/5000
  1. 移動配置文件位置
    /etc/sentinel/5000.conf
  2. 修改相關(guān)配置信息

    綁定端口

    port 5000

    綁定本級ip

    bind 192.168.xxx.xxx
    dir /var/sentinal/5000

    設(shè)定哨兵masterip

    sentinel monitor mymaster 192.168.xxx.xxx 6379 2
    sentinel down-after-milliseconds mymaster 30000
    sentinel failover-timeout mymaster 60000
    sentinel parallel-syncs mymaster 1
  3. 生產(chǎn)環(huán)境額外部署

    后臺啟動

    daemonize yes

    日志保存路徑

    logfile /var/log/sentinal/5000/sentinel.log
    mkdir -p /var/log/sentinal/5000
  • 4.2 啟動哨兵集群,并查看相關(guān)信息
  1. 啟動哨兵client端
    redis-cli -h 192.168.xxx.xxx -p 5000
  1. 查看相關(guān)信息
    sentinel master mymaster
    SENTINEL slaves mymaster
    SENTINEL sentinels mymaster
    SENTINEL get-master-addr-by-name mymaster
  • 4.3 哨兵的增加刪除和slave永久下線
    4.3.1 哨兵節(jié)點的增加和刪除

增加sentinal,會自動發(fā)現(xiàn);
刪除sentinal的步驟:
(1)停止sentinal進程

(2)SENTINEL RESET *,在所有sentinal上執(zhí)行,清理所有的master狀態(tài)
(3)SENTINEL MASTER mastername,在所有sentinal上執(zhí)行,查看所有sentinal對數(shù)量是否達(dá)成了一致

4.3.2 slave的永久下線

讓master摘除某個已經(jīng)下線的slave:SENTINEL RESET mastername,在所有的哨兵上面執(zhí)行.

五. redis 之集群模式

redis的集群模式為了解決系統(tǒng)的橫向擴展以及海量數(shù)據(jù)的存儲問題,如果你的數(shù)據(jù)量很大,那么就可以用redis cluster。
  redis cluster可以支撐N個redis master,一個master上面可以掛載多個slave,一般情況我門掛載一個到兩個slave,master在掛掉以后會主動切換到slave上面,或者當(dāng)一個master上面的slave都掛掉后,集群會從其他master上面找到冗余的slave掛載到這個master上面,達(dá)到了系統(tǒng)的高可用性。

1. redis cluster 的hash slot 算法

redis cluster有固定的16384個hash slot,對每個key計算CRC16值,然后對16384取模,可以獲取key對應(yīng)的hash slot;
  redis cluster中每個master都會持有部分slot,比如有3個master,那么可能每個master持有5000多個hash slot;
  hash slot讓node的增加和移除很簡單,增加一個master,就將其他master的hash slot移動部分過去,減少一個master,就將它的hash slot移動到其他master上去,移動hash slot的成本非常低;

2. redis cluster 簡單配置

2.1 redis cluster的重要配置

  • cluster-enabled <yes/no>

  • cluster-config-file <filename>:這是指定一個文件,供cluster模式下的redis實例將集群狀態(tài)保存在那里,包括集群中其他機器的信息,比如節(jié)點的上線和下限,故障轉(zhuǎn)移,不是我們?nèi)ゾS護的,給它指定一個文件,讓redis自己去維護.

  • cluster-node-timeout <milliseconds>:節(jié)點存活超時時長,超過一定時長,認(rèn)為節(jié)點宕機,master宕機的話就會觸發(fā)主備切換,slave宕機就不會提供服務(wù).

2.2 在三臺機器上啟動6個redis實例

  1. 修改redis.conf配置文件

    mkdir -p /etc/redis-cluster
    mkdir -p /var/log/redis
    mkdir -p /var/redis/7001

    port 7001
    cluster-enabled yes
    cluster-config-file /etc/redis-cluster/node-7001.conf
    cluster-node-timeout 15000
    daemonize yes
    pidfile /var/run/redis_7001.pid
    dir /var/redis/7001
    logfile /var/log/redis/7001.log
    bind 192.168.xxx.xxx
    appendonly yes

將上面的配置文件,在/etc/redis下放6個,分別為: 7001.conf,7002.conf,7003.conf,7004.conf,7005.conf,7006.conf

  1. 準(zhǔn)備生產(chǎn)環(huán)境的啟動腳本

在/etc/init.d下,放6個啟動腳本,分別為: redis_7001, redis_7002, redis_7003, redis_7004, redis_7005, redis_7006

每個啟動腳本內(nèi),都修改對應(yīng)的端口號

  1. 分別在3臺機器上,啟動6個redis實例

將每個配置文件中的slaveof給刪除(不要開啟從節(jié)點配置)

2.3 創(chuàng)建集群

  • 使用如下命令時報錯

    yum install -y ruby
    yum install -y rubygems
    gem install redis

redis requires Ruby version >= 2.2.2的報錯,查了資料發(fā)現(xiàn)是Centos默認(rèn)支持ruby到2.0.0,可gem 安裝redis需要最低是2.2.2

解決辦法是 先安裝rvm,再把ruby版本提升至2.3.3

  1. 安裝curl(centos7 已經(jīng)安裝不用重新安裝)

sudo yum install curl

  1. 安裝RVM

gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
curl -L get.rvm.io | bash -s stable

  1. 查詢rvm文件所在位置,并加載rvm配置

find / -name rvm -print
source /usr/local/rvm/scripts/rvm

  1. 查看rvm庫中已知的ruby版本,并安裝一個ruby版本

rvm list known
rvm install 2.3.4

  1. 使用一個ruby版本是指為默認(rèn),移除舊版本

rvm use 2.3.4 --default
rvm remove 2.0.0
ruby --version

  1. 安裝redis

gem install redis

使用redis-trib.rb命令創(chuàng)建集群

cp /usr/local/sftp/redis-3.2.8/src/redis-trib.rb /usr/local/bin

redis-trib.rb create --replicas 1 192.168.199.141:7001 192.168.199.141:7002 192.168.199.142:7003 192.168.199.142:7004 192.168.199.143:7005 192.168.199.143:7006

--replicas: 表示每個master有幾個slave

redis-trib.rb check 192.168.31.187:7001 查看狀體

3. 集群模式master擴容和節(jié)點移除

3.1 加入新master

mkdir -p /var/redis/7007

port 7007
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7007.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7007.pid
dir /var/redis/7007
logfile /var/log/redis/7007.log
bind 192.168.199.144
appendonly yes

以上相同配置完成后,設(shè)置啟動腳本進行啟動;然后用如下命令進行node節(jié)點添加:

redis-trib.rb add-node 192.168.199.144:7007 192.168.199.141:7001
redis-trib.rb check 192.168.199.141:7001

3.2 reshard一些數(shù)據(jù)過去

resharding的意思就是把一部分hash slot從一些node上遷移到另外一些node上
redis-trib.rb reshard 192.168.199.141:7001

3.3 添加node作為slave

進行上面的相同配置后,設(shè)定啟動腳本,執(zhí)行如下命令(其中masterid可以通過check命令進行查看):
redis-trib.rb add-node --slave --master-id 28927912ea0d59f6b790a50cf606602a5ee48108 192.168.199.144:7008 192.168.199.141:7001

3.4 刪除node

先用resharding將數(shù)據(jù)都移除到其他節(jié)點,確保node為空之后,才能執(zhí)行remove操作
redis-trib.rb del-node 192.168.199.141:7001 bd5a40a6ddccbd46a0f4a2208eb25d2453c2a8db

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容