
1、背景
例如,存在一套redis主從(主從節(jié)點(diǎn)在不同的主機(jī)上),應(yīng)用程序通過(guò)主庫(kù)的ip進(jìn)行讀寫操作。但是,主庫(kù)一旦出現(xiàn)故障,雖然有從庫(kù),且從庫(kù)提升為主庫(kù),但是應(yīng)用程序如果想使用從庫(kù)則必須修改配置,重啟應(yīng)用方可生效。如用此情況,則涉及的人員比較多,且應(yīng)用程序恢復(fù)使用的時(shí)間比較長(zhǎng)。對(duì)于此情況,可以采取以下2種解決方式解決:
配置VIP
在Redis主庫(kù)服務(wù)器上配置vip,當(dāng)主庫(kù)出現(xiàn)問(wèn)題時(shí),配置腳本將vip自動(dòng)切換至從節(jié)點(diǎn),并將從節(jié)點(diǎn)提升為讀寫狀態(tài)。應(yīng)用程序中配置的是vip,主庫(kù)異常時(shí),從庫(kù)自動(dòng)提升為主庫(kù)對(duì)外提供服務(wù),應(yīng)用程序無(wú)需做任何操作。
使用DNS
應(yīng)用程序通過(guò)配置內(nèi)網(wǎng)域名連接redis,DNS服務(wù)器對(duì)應(yīng)域名映射到redis主庫(kù)服務(wù)器IP。當(dāng)redis主庫(kù)異常時(shí),將redis從節(jié)點(diǎn)提升為讀寫主庫(kù),修改DNS域名映射關(guān)系至redis從節(jié)點(diǎn)ip,此時(shí)應(yīng)用程序也無(wú)需進(jìn)行操作。
注:
以上2種方式均存在缺陷,例如:
- vip方式存在問(wèn)題: 當(dāng)主從節(jié)點(diǎn)不在同一個(gè)機(jī)房或同一網(wǎng)段時(shí),將無(wú)法使用相同的vip。
- DNS方式:使用DNS方式將有DNS緩存問(wèn)題,即修改域名映射后域名仍可能解析到原主庫(kù)機(jī)器的ip。
vip配合哨兵的高可用方式將在后續(xù)介紹,本次先介紹DNS服務(wù)器配置及dns方式解決方案。
2、DNS服務(wù)配置
(1)安裝DNS服務(wù)
# 安裝bind相關(guān)工具
yum install bind bind-utils bind-devel bind-libs bind-chroot -y
2.2 修改配置文件
vim /etc/named.conf
## 編譯對(duì)應(yīng)內(nèi)容
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//
options {
// listen-on port 53 { 127.0.0.1; }; // 此行注釋
listen-on port 53 { any; }; // 添加此行
listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
// allow-query { localhost; }; // 注釋此行
allow-query { any; }; // 添加此行
forwarders {114.114.114.114; }; // 添加此行,這是在DNS服務(wù)器不知道域名解析的時(shí)候詢問(wèn)這個(gè)IP的主機(jī),這個(gè)IP的主機(jī)必須聯(lián)網(wǎng)
recursion yes;
dnssec-enable yes;
dnssec-validation yes;
/* Path to ISC DLV key */
bindkeys-file "/etc/named.iscdlv.key";
managed-keys-directory "/var/named/dynamic";
};
logging {
channel default_debug {
file "data/named.run";
severity dynamic;
};
};
zone "." IN {
type hint;
file "named.ca";
};
include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
(2)檢查語(yǔ)法
(3)啟動(dòng)DNS服務(wù)
(4)配置DNS正向解析文件
在/etc/named.rfc1912.zones添加正向解析配置。
vim /etc/named.rfc1912.zones # 此文件名在上面步驟的/etc/named.conf文件末尾有指定
## 此文件末尾追加如下內(nèi)容
zone "redis.com" IN { // redis.com 名自定義,即需要解析的域名
type master; // dns域類型為master
file "redis.com.zone"; // redis.com.zone 文件名自定義,后續(xù)文件名需與此一致
allow-update { none; };
};
根據(jù)上一步的情況,配置解析文件。
# 拷貝文件
cp -p named.localhost redis.com.zone # 拷貝文件,注意要連同權(quán)限一起拷貝,因權(quán)限不一致,啟動(dòng)會(huì)報(bào)錯(cuò)
vim redis.com.zone
$TTL 1D
@ IN SOA www.redis.com. rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS www.redis.com.
dns IN A 192.168.56.208
www IN A 192.168.56.208
(5)配置DNS反向解析文件
在/etc/named.rfc1912.zones添加反向解析配置。
可以將正向解析與反向解析配置在一個(gè)文件里,即file配置為相同的文件名。本次分開配置來(lái)演示。
vim /etc/named.rfc1912.zones # 此文件名在上面步驟的/etc/named.conf文件末尾有指定
## 此文件末尾追加如下內(nèi)容
zone "56.168.192.in-addr.arpa" IN {
type master;
file "redis.com.local";
allow-update { none; };
};
根據(jù)上一步的情況,配置解析文件。
# 拷貝文件
cp -p named.localhost redis.com.local # 拷貝文件,注意要連同權(quán)限一起拷貝,因權(quán)限不一致,啟動(dòng)會(huì)報(bào)錯(cuò)
vim redis.com.local
$TTL 1D
@ IN SOA www.redis.com. rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS @
A 192.168.56.208
AAAA ::1
208 IN PTR www.redis.com.
(6)重啟DNS服務(wù)
/etc/init.d/named restart
(7)測(cè)試DNS服務(wù)器
在另一臺(tái)主機(jī)上測(cè)試DNS是否可用,操作步驟如下。
# 修改域名解析文件
vim /etc/resolv.conf
# 將創(chuàng)建的DNS服務(wù)器地址添加至此文件
nameserver 192.168.56.209

正向解析測(cè)試。
nslookup www.redis.com
# 結(jié)果如下
Server: 192.168.56.209
Address: 192.168.56.209#53
Name: www.redis.com
Address: 192.168.56.208

反向解析測(cè)試。
nslookup 192.168.56.208
# 結(jié)果如下:
Server: 192.168.56.209
Address: 192.168.56.209#53
208.56.168.192.in-addr.arpa name = www.redis.com.

ping 域名測(cè)試。
ping www.redis.com
# 結(jié)果如下
PING www.redis.com (192.168.56.208) 56(84) bytes of data.
64 bytes from www.redis.com (192.168.56.208): icmp_seq=1 ttl=64 time=0.229 ms
64 bytes from www.redis.com (192.168.56.208): icmp_seq=2 ttl=64 time=0.287 ms
64 bytes from www.redis.com (192.168.56.208): icmp_seq=3 ttl=64 time=0.276 ms
64 bytes from www.redis.com (192.168.56.208): icmp_seq=4 ttl=64 time=0.224 ms

至此,DNS服務(wù)器搭建并測(cè)試完畢,下面進(jìn)入正題。
3、搭建Redis主從
關(guān)于redis搭建之前的文章已經(jīng)介紹過(guò),詳細(xì)信息可參考?xì)v史文章
?https://www.cnblogs.com/gjc592/p/11098047.html。
1、搭建主、從節(jié)點(diǎn)redis實(shí)例,部署過(guò)程完全一致
依賴包安裝。
yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make gcc-c++ libstdc++-devel tclb) 安裝包準(zhǔn)備
可以從官網(wǎng) https://redis.io下載最新版redis。
wget http://download.redis.io/releases/redis-4.0.14.tar.gz
tar -zxvf redis-4.0.14.tar.gz
編譯、安裝。
cd redis-4.0.14
make
make install
創(chuàng)建目錄、修改配置文件、啟動(dòng)redis。
建議創(chuàng)建單獨(dú)的redis目錄。
# 創(chuàng)建目錄
mkdir -p /data/redis/redis6379
# 拷貝配置文件
cp redis.conf /data/redis/redis6379/
# 修改配置文件
vim redis.conf
修改如下部分
bind 0.0.0.0 可以指定所有地址均可訪問(wèn),若指定對(duì)應(yīng)網(wǎng)段或IP 修改此處即可
daemonize yes 放在后臺(tái)執(zhí)行,建議修改為yes
pidfile /data/redis/redis6379/redis_6379.pid 指定pid文件目錄及文件名
logfile "/data/redis/redis6379/redis6379.log" 指定log文件目錄及文件名
# 其他參數(shù)在生產(chǎn)環(huán)境中可適當(dāng)調(diào)整
# 啟動(dòng)redis
redis-server redis.conf
2、配置主從
在從服務(wù)器執(zhí)行如下命令配置主從。
127.0.0.1:6379> slaveof 192.168.56.208 6379 ## 即輸入對(duì)應(yīng)的redis主庫(kù)的ip 即端口
查看主從狀態(tài)。
127.0.0.1:6379> info Replication
## 結(jié)果如下
# Replication
role:slave
master_host:192.168.56.208
master_port:6379
master_link_status:up // up代表已正常同步
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:266
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:22830eb406e63f0a85d3d912a44e1b80dba6c860
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:266
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:266
至此,redis主從同步配置完成。
4、測(cè)試域名方式操作redis
編寫程序,測(cè)試使用域名方式連接redis
注意:程序運(yùn)行機(jī)器需添加對(duì)應(yīng)的內(nèi)網(wǎng)DNS服務(wù)器,即2.8中的操作。本次使用python進(jìn)行測(cè)試
1、安裝Python所需的包-- redis
python連接redis需安裝redis包,關(guān)于Python升級(jí),pip安裝等歷史文章里均有,如有需要可以參考操作
2、編寫簡(jiǎn)單的Python操作redis的測(cè)試程序
vim test_redis.py
# 內(nèi)容如下
#!/usr/bin/python
# coding=utf-8
import redis
v_ip ='www.redis.com'
v_port = 6379
v_passwd=''
r = redis.Redis(host=v_ip,port=v_port,password=v_passwd,db=0)
r.set('test_key1','test1')
result = r.get('test_key1')
print result ,"設(shè)置鍵成功并獲取到values"
r.delete('test_key1')
print "刪除鍵完畢"
result1 = r.get('test_key1')
print result1,"驗(yàn)證刪除成功"
3、運(yùn)行測(cè)試程序,看是否能通過(guò)域名操作成功
python test_redis.py
# 結(jié)果如下
test1 設(shè)置鍵成功并獲取到values
刪除鍵完畢
None 驗(yàn)證刪除成功
有圖有真相。

說(shuō)明,使用域名操作redis正常。
5、模擬redis主庫(kù)異常
1、關(guān)閉主庫(kù)
127.0.0.1:6379> shutdown
not connected> exit
2、測(cè)試程序使用redis情況
python test_redis.py
## 報(bào)錯(cuò)
Traceback (most recent call last):
File "test_redis.py", line 9, in <module>
r.set('test_key1','test1')
File "/usr/local/python2.7/lib/python2.7/site-packages/redis/client.py", line 1451, in set
return self.execute_command('SET', *pieces)
File "/usr/local/python2.7/lib/python2.7/site-packages/redis/client.py", line 772, in execute_command
connection = pool.get_connection(command_name, **options)
File "/usr/local/python2.7/lib/python2.7/site-packages/redis/connection.py", line 994, in get_connection
connection.connect()
File "/usr/local/python2.7/lib/python2.7/site-packages/redis/connection.py", line 497, in connect
raise ConnectionError(self._error_message(e))
redis.exceptions.ConnectionError: Error 111 connecting to www.redis.com:6379. Connection refused.
即,此時(shí)redis已無(wú)法使用。
3、提升從庫(kù)為讀寫庫(kù)
從庫(kù)默認(rèn)為只讀,斷開主從復(fù)制后將會(huì)變?yōu)樽x寫庫(kù)。
查看此時(shí)從庫(kù)復(fù)制狀態(tài)。
127.0.0.1:6379> info Replication
# Replication
role:slave
master_host:192.168.56.208
master_port:6379
master_link_status:down // 主從同步已斷開
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:3215
master_link_down_since_seconds:98
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:22830eb406e63f0a85d3d912a44e1b80dba6c860
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:3215
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:3215
斷開主從同步。
127.0.0.1:6379> slaveof no one
OK
127.0.0.1:6379> info Replication
# Replication
role:master // 斷開后,已變成主庫(kù)
connected_slaves:0
master_replid:180df5fbdc8cf8999b27ad42e6c57eb3be31b6b2
master_replid2:22830eb406e63f0a85d3d912a44e1b80dba6c860
master_repl_offset:3215
second_repl_offset:3216
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:3215
因此時(shí)域名仍指向原主庫(kù),所以程序依舊異常。
6、切換域名指向
1、修改配置文件
將DNS服務(wù)中對(duì)應(yīng)域名的IP地址改為從庫(kù)地址。
vim redis.com.zone
## 修改
$TTL 1D
@ IN SOA www.redis.com. rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS www.redis.com.
dns IN A 192.168.56.207
www IN A 192.168.56.207
vim redis.com.local
# 修改后
$TTL 1D
@ IN SOA www.redis.com. rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS @
A 192.168.56.207
AAAA ::1
207 IN PTR www.redis.com.
2、重啟DNS服務(wù)或刷新緩存
本次測(cè)試直接重啟DNS服務(wù)
/etc/init.d/named restart
3、簡(jiǎn)單測(cè)試域名解析情況
nslookup www.redis.com #正向測(cè)試DNS
# 結(jié)果如下
nslookup www.redis.com
Server: 192.168.56.209
Address: 192.168.56.209#53
Name: www.redis.com
Address: 192.168.56.207
說(shuō)明已修改成功
7、最終測(cè)試
再次使用python 程序測(cè)試操作redis情況。
python test_redis.py
# 運(yùn)行結(jié)果
test1 設(shè)置鍵成功并獲取到values
刪除鍵完畢
None 驗(yàn)證刪除成功
此時(shí)應(yīng)用程序未做任何修改,可以正常使用。