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