1. 程式人生 > >redis高可用之DNS篇

redis高可用之DNS篇

1.  背景

例如,存在一套redis主從(主從節點在不同的主機上),應用程式通過主庫的ip進行讀寫操作。 但是,主庫一旦出現故障,雖然有從庫,且從庫提升為主庫,但是應用程式如果想使用從庫則必須修改配置,重啟應用方可生效。如用此情況,則涉及的人員比較多,且應用程式恢復使用的時間比較長。對於此情況,可以採取以下2種解決方式解決:

a)  配置VIP

在Redis主庫伺服器上配置vip,當主庫出現問題時,配置指令碼將vip自動切換至從節點,並將從節點提升為讀寫狀態。應用程式中配置的是vip,主庫異常時,從庫自動提升為主庫對外提供服務,應用程式無需做任何操作。

b)  使用DNS

應用程式通過配置內網域名連線redis,DNS伺服器對應域名對映到redis主庫伺服器IP。 當redis主庫異常時,將redis從節點提升為讀寫主庫,修改DNS域名對映關係至redis從節點ip,此時應用程式也無需進行操作。

注:

以上2種方式均存在缺陷,例如:

  • vip方式存在問題:  當主從節點不在同一個機房或同一網段時,將無法使用相同的vip。
  • DNS方式: 使用DNS方式將有DNS快取問題,即修改域名對映後域名仍可能解析到原主庫機器的ip。

vip配合哨兵的高可用方式將在後續介紹,本次先介紹DNS伺服器配置及dns方式解決方案。

 

2.  DNS服務配置

2.1  安裝DNS服務

# 安裝bind相關工具
yum  install  bind  bind-utils  bind-devel bind-libs  bind-chroot  -y

2.2  修改配置檔案

vim /etc/named.conf
##  編譯對應內容
// 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伺服器不知道域名解析的時候詢問這個IP的主機,這個IP的主機必須聯網
        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.3   檢查語法

named-checkconf

2.4   啟動DNS服務

/etc/init.d/named  start

2.5  配置DNS正向解析檔案

a)  在/etc/named.rfc1912.zones新增正向解析配置

vim /etc/named.rfc1912.zones  # 此檔名在上面步驟的/etc/named.conf檔案末尾有指定

##  此檔案末尾追加如下內容


zone "redis.com" IN {                         //  redis.com 名自定義,即需要解析的域名
        type master;                          //  dns域型別為master
        file "redis.com.zone";                //  redis.com.zone 檔名自定義,後續檔名需與此一致
        allow-update { none; };
};

b)  根據上一步的情況,配置解析檔案

# 拷貝檔案
cp -p  named.localhost redis.com.zone  # 拷貝檔案,注意要連同許可權一起拷貝,因許可權不一致,啟動會報錯

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

2.6  配置DNS反向解析檔案

a)  在/etc/named.rfc1912.zones新增反向解析配置

可以將正向解析與反向解析配置在一個檔案裡,即file配置為相同的檔名。本次分開配置來演示

vim /etc/named.rfc1912.zones  # 此檔名在上面步驟的/etc/named.conf檔案末尾有指定

##  此檔案末尾追加如下內容

zone "56.168.192.in-addr.arpa" IN {   
        type master;
        file "redis.com.local";
        allow-update { none; };
};

b)   根據上一步的情況,配置解析檔案

# 拷貝檔案
cp -p  named.localhost redis.com.local  # 拷貝檔案,注意要連同許可權一起拷貝,因許可權不一致,啟動會報錯

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.

2.7  重啟DNS服務

/etc/init.d/named restart

2.8  測試DNS伺服器

在另一臺主機上測試DNS是否可用,操作步驟如下。

# 修改域名解析檔案
vim /etc/resolv.conf

# 將建立的DNS伺服器地址新增至此檔案
nameserver   192.168.56.209

 正向解析測試

 nslookup www.redis.com
# 結果如下
Server:        192.168.56.209
Address:    192.168.56.209#53

Name:    www.redis.com
Address: 192.168.56.208

反向解析測試

nslookup  192.168.56.208
#  結果如下:
Server:        192.168.56.209
Address:    192.168.56.209#53

208.56.168.192.in-addr.arpa    name = www.redis.com.

 

 ping 域名測試

 ping  www.redis.com
#  結果如下
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伺服器搭建並測試完畢,下面進入正題。

 

3.  搭建Redis主從

 關於redis搭建之前的文章已經介紹過,詳細資訊可參考歷史文章https://www.cnblogs.com/gjc592/p/11098047.html。

3.1  搭建主、從節點redis例項,部署過程完全一致

a)  依賴包安裝

yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make gcc-c++ libstdc++-devel tcl

b)  安裝包準備

可以從官網  https://redis.io下載最新版redis

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

c)   編譯、安裝

cd   redis-4.0.14
make 
make install

d) 建立目錄、修改配置檔案、啟動redis

建議建立單獨的redis目錄

#  建立目錄
mkdir -p /data/redis/redis6379

#  拷貝配置檔案
cp redis.conf  /data/redis/redis6379/

#  修改配置檔案
vim redis.conf
修改如下部分
bind  0.0.0.0     可以指定所有地址均可訪問,若指定對應網段或IP 修改此處即可
daemonize yes   放在後臺執行,建議修改為yes
pidfile /data/redis/redis6379/redis_6379.pid  指定pid檔案目錄及檔名
logfile "/data/redis/redis6379/redis6379.log" 指定log檔案目錄及檔名

# 其他引數在生產環境中可適當調整

# 啟動redis
redis-server redis.conf

 3.2  配置主從

在從伺服器執行如下命令配置主從

127.0.0.1:6379> slaveof   192.168.56.208  6379    ##  即輸入對應的redis主庫的ip 即埠

檢視主從狀態

127.0.0.1:6379> info Replication
## 結果如下 # 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.  測試域名方式操作redis

編寫程式,測試使用域名方式連線redis

注意:程式執行機器需新增對應的內網DNS伺服器,即2.8中的操作。本次使用python進行測試

4.1  安裝Python所需的包-- redis

python連線redis需安裝redis包,關於Python升級,pip安裝等歷史文章裡均有,如有需要可以參考操作

pip  install redis

4.2  編寫簡單的Python操作redis的測試程式

 vim test_redis.py 

#  內容如下

#!/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 ,"設定鍵成功並獲取到values"
r.delete('test_key1')
print  "刪除鍵完畢"
result1 = r.get('test_key1')
print result1,"驗證刪除成功"

4.3   執行測試程式,看是否能通過域名操作成功

 python test_redis.py 
# 結果如下
test1 設定鍵成功並獲取到values
刪除鍵完畢
None 驗證刪除成功

有圖有真相

說明,使用域名操作redis正常。

5.  模擬redis主庫異常

5.1  關閉主庫

127.0.0.1:6379> shutdown
not connected> exit

 

5.2  測試程式使用redis情況

python test_redis.py 
##  報錯
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.

即,此時redis已無法使用

5.3   提升從庫為讀寫庫

從庫預設為只讀,斷開主從複製後將會變為讀寫庫

a)  檢視此時從庫複製狀態

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

b)  斷開主從同步

127.0.0.1:6379> slaveof  no one
OK
127.0.0.1:6379> info Replication
# Replication
role:master                                             // 斷開後,已變成主庫
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

因此時域名仍指向原主庫,所以程式依舊異常。

6. 切換域名指向

6.1 修改配置檔案

將DNS服務中對應域名的IP地址改為從庫地址

 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.

6.2  重啟DNS服務或重新整理快取

本次測試直接重啟DNS服務

/etc/init.d/named  restart

6.3  簡單測試域名解析情況

nslookup www.redis.com   #正向測試DNS
# 結果如下
nslookup www.redis.com
Server:        192.168.56.209
Address:    192.168.56.209#53

Name:    www.redis.com
Address: 192.168.56.207

說明已修改成功

7.  最終測試

再次使用python 程式測試操作redis情況

python test_redis.py 
# 執行結果
test1 設定鍵成功並獲取到values
刪除鍵完畢
None 驗證刪除成功

此時應用程式未做任何修改,可以正常使用。

 

ps:

以上測試步驟中部分有省略,如果錯誤,歡迎指正。

耿小廚已開通個人微信公眾號,想進一步溝通或想了解其他文章的同學可以關注我

&n