Redis 主從,集群--實戰
1、架構
2、Redis主從數據同步的步驟
3、安裝部署
3.1 基本環境
兩臺Centos 6.5 操作系統 ,分別關閉selinux,以及防火墻。
master: 192.168.0.250
slave: 192.168.0.251
安裝C語言編輯器
yum install gcc gcc-c++ -y
4.2.下載編譯
使用的版本是: redis-3.2.6
tar zxvf redis-3.2.6.tar.gz
>cd redis-3.2.6
>make
>make PREFIX=/usr/local/redis install
4.3 創建redis後續使用的目錄
mkdir -p /usr/local/redis/{data,log,conf}
註:data是rdb文件保存位置,log是日誌文件保存位置,conf是配置文件保存位置
拷貝配置文件
cp /root/redis-3.2.6/sentinel.conf /usr/local/redis/conf
cp /root/redis-3.2.6/redis.conf /usr/local/redis/conf
4.4修改配置文件
修改主服務器配置文件
vim redis.conf
bind 192.168.0.250
daemonize yes
pidfile "/usr/local/redis/redis_6379.pid"
loglevel verbose
logfile "/usr/local/redis/log/redis.log"
dir "/usr/local/redis/data"
masterauth "zhangshuhao"
requirepass "zhangshuhao"
其余默認配置
修改從配置文件
vim redis.conf
bind 192.168.0.250
daemonize yes
pidfile "/usr/local/redis/redis_6379.pid"
loglevel verbose
logfile "/usr/local/redis/log/redis.log"
dir "/usr/local/redis/data"
masterauth "zhangshuhao"
requirepass "zhangshuhao"
slaveof 192.168.0.250 6379
4.5 啟動和測試
主機: redis-server ../conf/redis.conf
從機: redis-server ../conf/redis.conf
在主機上啟動redis客戶端:
redis-cli -h 192.168.0.250
>set k1 v1
>get k1
"v1"
.登陸從機,並在從機上啟動客戶端:
redis-cli -h 192.168.0.251
>get k1
"v1"
開啟哨兵機制:(我是在從節點開啟的)
vim /usr/local/redis/conf/sentinel.conf
sentinel monitor mymaster 192.168.0.251 6379 1
sentinel down-after-milliseconds mymaster 10000
sentinel auth-pass mymaster zhangshuhao
啟動
./redis-sentinel ../conf/sentinel.conf &
Redis的數據回寫機制
Redis的數據回寫機制分同步和異步兩種,
同步回寫即SAVE命令,主進程直接向磁盤回寫數據。在數據大的情況下會導致系統假死很長時間,所以一般不是推薦的。
異步回寫即BGSAVE命令,主進程fork後,復制自身並通過這個新的進程回寫磁盤,回寫結束後新進程自行關閉。由於這樣做不需要主進程阻塞,系統不會假死,一般默認會采用這個方法。
個人感覺方法2采用fork主進程的方式很拙劣,但似乎是唯一的方法。內存中的熱數據隨時可能修改,要在磁盤上保存某個時間的內存鏡像必須要凍結。凍結就會導致假死。fork一個新的進程之後等於復制了當時的一個內存鏡像,這樣主進程上就不需要凍結,只要子進程上操作就可以了。
在小內存的進程上做一個fork,不需要太多資源,但當這個進程的內存空間以G為單位時,fork就成為一件很恐怖的操作。何況在16G內存的主機上fork 14G內存的進程呢?肯定會報內存無法分配的。更可氣的是,越是改動頻繁的主機上fork也越頻繁,fork操作本身的代價恐怕也不會比假死好多少。
找到原因之後,直接修改/etc/sysctl.conf內核參數vm.overcommit_memory= 1
sysctl -p
Linux內核會根據參數vm.overcommit_memory參數的設置決定是否放行。
如果 vm.overcommit_memory = 1,直接放行
vm.overcommit_memory = 0:則比較 此次請求分配的虛擬內存大小和系統當前空閑的物理內存加上swap,決定是否放行。
vm.overcommit_memory= 2:則會比較進程所有已分配的虛擬內存加上此次請求分配的虛擬內存和系統當前的空閑物理內存加上swap,決定是否放行。
搭建redis分布式集群
1、架構圖
藍色的部分為redis集群中的每個node節點,節點之間通過ping命令,測試相互是否連接正常,普通集群沒有主從區分,連接任何一個節點操作,都可以轉發到其他任意一個節點
1、 redis容錯機制
每個redis提供了節點之間相互發送ping命令,用於測試每個節點的健康狀態,集群中連接正常的節點收到其他接節點發送的ping命令時,會返回一個pong字符串
Redis投票機制:如果一個節點A給B發送ping沒有得到pong返回,那麽A就會通知其他節點在次給B發送ping,如果集群中超過一半的節點給B發送ping都沒有得到返回,那麽B就被坐實game over了,所以為了避免單點故障,一半都會為redis的每個節點提供了備份節點,B節點掛掉之後立馬啟動B的節點服務器。
2、 集群存儲的原理
在集群當中每個節點上的數據都不一樣,(一樣就是主備了)把數據都分散存放到各個節點上進行存儲。
Redis中槽slof就用於圈定當前節點的存儲範圍,為分散存儲使用hash算法,確定什麽值放到哪個槽裏
3、Redis 持久化機制
Redis提供了2中數據持久化方式:
Snapshotting:定時的將Redis內存的當前狀態保存到RDB文件中,持久化到硬盤。
AOF(append-only file):將所有的command操作保存到aof文件中,AOP使得同步頻率很高,數據即便丟失,粒度也很小,但性能上有所犧牲。默認數據持久化會2s同步一次,也可以進行配置改變同步頻率。
4、安裝部署
1)環境三臺服務器分別關閉iptables ,selinux centOS6.5操作系統(要讓集群正常的工作至少需要三個主節點,在這裏創建6個redis節點,其中三個為主節點,三個節點為從節點)
192.168.2.41:7000
192.168.2.41:7001
192.168.2.41:7002
192.168.2.41:7003
192.168.2.41:7004
192.168.2.41:7005
2)下載安裝包並上傳到服務器解壓,編譯
http://download.redis.io/releases/ 在這裏我使用的是redis 3.2.6
tar zxvf redis-3.2.6.tar.gz &&mv redis-3.2.6 /usr/local/redis3.0 &&cd /usr/local/redis3.0 && make && make install
3)創建集群所需要的目錄並進行拷貝
mkdir -p /usr/local/cluster
mkdir -p /usr/local/cluster/7000
mkdir -p /usr/local/cluster/7001
mkdir -p /usr/local/cluster/7002
mkdir -p /usr/local/cluster/7003
mkdir -p /usr/local/cluster/7004
mkdir -p /usr/local/cluster/7005
cp -rf /usr/local/redis3.0/* /usr/local/cluster/7000/
cp -rf /usr/local/redis3.0/* /usr/local/cluster/7001/
cp -rf /usr/local/redis3.0/* /usr/local/cluster/7002/
cp -rf /usr/local/redis3.0/* /usr/local/cluster/7003/
cp -rf /usr/local/redis3.0/* /usr/local/cluster/7004/
cp -rf /usr/local/redis3.0/* /usr/local/cluster/7005/
4)修改配置文件redis.conf (針對不同的進程修改對應的端口號)
port 7000
daemonize yes #在後臺運行
cluster-enabled yes #打開服務器集群模式
cluster-config-file nodes.conf #redis集群配置文件(自動生成)
cluster-node-timeout 5000 #節點連接超時時間
appendonly yes #同時開啟dump,以及AOF
requirepass vjifen #設置客戶端訪問密碼
5)啟動6個redis(啟動成功之後 ps –ef |grep redis 查看)
cd /usr/local/cluster/7000/src
redis-server ../redis.conf
cd /usr/local/cluster/7001/src
redis-server ../redis.conf
cd /usr/local/cluster/7002/src
redis-server ../redis.conf
cd /usr/local/cluster/7003/src
redis-server ../redis.conf
cd /usr/local/cluster/7004/src
redis-server ../redis.conf
cd /usr/local/cluster/7005/src
redis-server ../redis.conf
6.1)創建集群
cd /usr/local/redis3.0/src
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
在啟動時會報錯,因為執行的內容需要安裝ruby環境
報錯信息:error:/usr/bin/env: ruby: No such file or directory
yum install ruby -y 在這裏我使用yum安裝
6.2)在次執行
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
依然會報錯,報錯信息為:(他告訴你找不到rubygems,缺少rubygems組件)
./redis-trib.rb:24:in `require': no such file to load -- rubygems (LoadError)
from ./redis-trib.rb:24
所以安裝 yum install rubygems -y
6.3)在次創建集群
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
還會報錯,提示缺少redis的接口,錯誤內容為:
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- redis (LoadError)
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from ./redis-trib.rb:25
在這裏我安裝gem install redis –version 3.0.0
ERROR: Could not find a valid gem 'redis' (= 3.0.0) in any repository
ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError)
在安裝時報錯需要手動下載並安裝:
wget https://rubygems.global.ssl.fastly.net/gems/redis-3.2.1.gem
gem install -l ./redis-3.2.1.gem
6.4)再次創建集群
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
本次成功創建
>>> Creating cluster
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
>>> Performing hash slots allocation on 6 nodes... #首先嘗試連接給定的六個節點,檢查他們是否存在
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002 #在確定這些節點都連接成功之後,redistrib.rb,在將7000/7001/7002設置為主節點,而7003/7004/7005 則被自動設置為三個主節點的從節點
M: 2022f24d581b4a7c3342e3245c32927cbd5ec16d 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: 37b7008f80f8c21a698da8cb1f1b32db8c0c415c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: ac6dc5fa96e856b34c1ba4c3814394e4ebb698dd 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
S: b5b76d70bbb0dbf3e7df8a38f1259e95e2054721 127.0.0.1:7003 #對三個主節點,redis-trib.rb會分別為他們支配5461/5462/5461個槽(默認情況下使用平均分配)
replicates 2022f24d581b4a7c3342e3245c32927cbd5ec16d
S: 6881f8fef9c25da486f320ebf2ead39c1502db4c 127.0.0.1:7004
replicates 37b7008f80f8c21a698da8cb1f1b32db8c0c415c
S: f090526d32cced97731eef2a2e1722a7bac7d9ea 127.0.0.1:7005
replicates ac6dc5fa96e856b34c1ba4c3814394e4ebb698dd
Can I set the above configuration? (type 'yes' to accept): yes #在這裏他會問你上邊的配置有沒有問題,我選擇了yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 2022f24d581b4a7c3342e3245c32927cbd5ec16d 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: 37b7008f80f8c21a698da8cb1f1b32db8c0c415c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: ac6dc5fa96e856b34c1ba4c3814394e4ebb698dd 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
M: b5b76d70bbb0dbf3e7df8a38f1259e95e2054721 127.0.0.1:7003
slots: (0 slots) master
replicates 2022f24d581b4a7c3342e3245c32927cbd5ec16d
M: 6881f8fef9c25da486f320ebf2ead39c1502db4c 127.0.0.1:7004
slots: (0 slots) master
replicates 37b7008f80f8c21a698da8cb1f1b32db8c0c415c
M: f090526d32cced97731eef2a2e1722a7bac7d9ea 127.0.0.1:7005
slots: (0 slots) master
replicates ac6dc5fa96e856b34c1ba4c3814394e4ebb698dd
#redis-trib.rb會對集群進行測試,檢查是否每個節點都按照原先的展示的配置設置好了
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered. #如果整個集群數據庫16384個槽都有節點在處理,那麽集群就會進入線上狀態,之後用戶就可以開始想集群發送命令請求了
7)集群訪問
目前最主要的redis集群客戶端:
1、redis-rb-cluster:antirez 使用 Ruby 編寫的 Redis 集群客戶端,集群客戶端的官方實現;
2、predis:Redis 的 PHP 客戶端,支持集群功能;
3、jedis:Redis 的 JAVA 客戶端,支持集群功能;
4、StackExchange.Redis:Redis 的 C# 客戶端,支持集群功能;
5、內置的 redis-cli :在啟動時給定 -c 參數即可進入集群模式,支持部分集群功能;
為了讓實例保持簡單,我們在這裏使用集群模式的redis-cli來進行測試
[root@zsh src]# ./redis-cli -p 7000 -c
127.0.0.1:7001> auth zhangshuhao
OK
127.0.0.1:7001> set name zsh
OK
127.0.0.1:7001> get name
"zsh"
127.0.0.1:7001> keys *
1) "name"
九、redis持久化方式
Redis持久化---兩種方式
Redis提供了兩種持久化的方式,分別是RDB(redis Database )和AOF (append Only File)
RDB:簡而言之,就是在不同的時間點,將redis存儲的數據生成快照並存儲到磁盤等介質上;
AOF:則是換了一個角度來實現持久化,那就是將redis執行過的所有寫指令記錄下來,在下次redis重新啟動時,只要把這些指令從前到後在執行一遍就可以實現數據恢復了。
Redis持久化---RDB
RDB方式是將redis某一時刻的數據持久化到磁盤中,是一種快照式的持久化方法。
Redis在進行數據持久化的過程中,會將數據寫入到一個臨時文件中,待持久或過程都結束了,才會用這個臨時文件替換上次持久化好的文件。正是這種特性,讓我們可以隨時隨地進行備份,因為快照文件總是完整可用的。
對於RDB方式,redis會單獨創建fork一個子進程來進行持久化,而主進程是不會進行任何io操作的,這樣就確保了redis極高的性能
如果需要僅此能大規模數據的恢復,且對於數據恢復的完整性不是非常敏感,那麽RDB方式就不太適合,因為即使每5分鐘都持久化一次,當redis故障時,仍然會有近5分鐘的數據丟失,所以熱鍍絲還提供了另一種持久化方式,那就是AOF
Redis持久化—AOF
AOF(Append Only File),即只允許追加不允許改寫的文件。
AOF方式是將執行過的寫指令記錄下來,在數據恢復時按照從前到後的順序在將指令近行一遍
Redis 主從,集群--實戰