在60分钟内,通过市场将Redis Sentinel环境搭建起来
Redis 哨兵
Redis是一个开源的内存数据结构存储系统,具备内置的事务和复制功能。Redis可以配置为主从复制结构的Redis复制,但也有另一种重点放在高可用性上的部署结构,即Redis Sentinel。Redis Sentinel可以检测主服务器故障,并动态将从服务器升级为主服务器。主服务器和从服务器始终具有相同的数据配置。Redis还可以拥有多个主服务器,并将数据分片并分布在多个服务器上以实现Redis Cluster。Redis Cluster可用于分布数据,以分散负载,但为保持高可用性,需要每个主服务器都有其副本,这可能会导致冗余的配置。Redis Sentinel是一个平衡的功能,最小配置为3个节点,可以轻松保证高可用性。
本文参考了以下文档,旨在帮助初学者轻松配置Redis Sentinel。您可以在60分钟内安装和确认Redis Sentinel的配置。
被安装的配置
安装的方式是基于 Redis 官方网站 https://redis.io/docs/management/sentinel/ 中的 “basic setup with three boxes” 模式。
+----+
| M1 |
| S1 |
+----+
|
+----+ | +----+
| R2 |----+----| R3 |
| S2 | | S3 |
+----+ +----+
Configuration: quorum = 2
该系统由三个节点组成,一个主节点(M)和两个副本节点(R)。每个节点都有一个哨兵代理(S)运行,哨兵会决定哪台服务器应该成为主节点。哨兵进程进行多数投票,如果配置正确,将选择获得两票一致的服务器作为主节点(quorum = 2)。
安装过程和命令
从市场安装的主要组成要素包括以下内容。
-
- redis server
-
- redis sentinel
-
- redis-cli
- firewalld
火墙 (firewalld)被引入用于保护 Redis 服务器。如果不需要的话,可以停止使用。由于这次不希望允许不必要的访问,因此将继续使用 firewalld。
安装
请打开 www.linode.com 网站并登录到 Linode 控制台,然后在 Marketplace 中选择 Redis Sentinel。
选择下面的计算资源模型。由于Redis是一个内存中的数据存储,因此推荐选择高内存型,但本次选择Linode 2GB(2GB内存)。
安装只花了大约23分钟就完成了。
确认的方式
检查新创建实例的名称。标签名的末尾含有数字1/2/3之一。复制实例的(公共)IP地址。
使用ssh进行登录。
% ssh user@{Public_IP_Address}
在 /etc/hosts 中,Redis Sentinel Cluster 被注册了三个私有 IP。通过使用主机名来关注服务器角色的变化,可以更加直观地理解。
# Redis
192.168.198.87 redissentinel-tokyo1
192.168.198.103 redissentinel-tokyo2
192.168.198.112 redissentinel-tokyo3
# END redis servers
如下文所述,Redis服务器的访问信息写在我创建的用户帐户的 ~/.deployment-secrests.txt 文件夹下。请注意,这个文件夹不在root用户的目录下。
这是用户名称为 User 的示例。
user@redissentinel-tokyo1:~$ cat .deployment-secrets.txt
# BEGIN ANSIBLE MANAGED BLOCK
# system user
user: user
password: YOUR_ACCOUNT_LINUX_PASSWORD
# redis password
redis-cli --askpass --tls --cacert /etc/redis/tls/ca.crt:
y+8erSZr9YHAUIzA19zkxaS/8d+kjx4tMJXXXXXXXXXX
# END ANSIBLE MANAGED BLOCK
为了立即应用配置内容,请使用source命令启用。
source .bashrc
(红哨兵-东京1) 主机的连接测试
在进行到这一步的工作中,准备工作已经完成,可以开始使用redis-cli了。执行~/.deployment-secrets.txt文件中记录的命令。–askpass可以省略。由于/etc/redis/tls/ca.crt文件需要root权限才能访问,因此如果要以一般用户身份执行,请将文件复制到可以访问的位置。
redis-cli --tls --cacert /etc/redis/tls/ca.crt
成功登录后,输入ping命令。如果返回PONG,则表示功能正常。
root@redissentinel-tokyo1:~# redis-cli --tls --cacert /etc/redis/tls/ca.crt
127.0.0.1:6379> ping
PONG
输入info replication命令,就可以看到role:master。这表示该服务器是主服务器。
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.198.112,port=6379,state=online,offset=397294,lag=1
slave1:ip=192.168.198.103,port=6379,state=online,offset=397294,lag=1
master_failover_state:no-failover
master_replid:fac9e97e4769636aa327dbdf17c54bbfe8e2a5dc
master_replid2:e545c6cdcac628dbf0851c2521c3c8efa6b9df07
master_repl_offset:397581
second_repl_offset:5818
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:5818
repl_backlog_histlen:391764
我正在操作数据。成功插入了以scott为键的tiger数据。
127.0.0.1:6379> get scott
(nil)
127.0.0.1:6379> set scott tiger
OK
127.0.0.1:6379> get scott
"tiger"
127.0.0.1:6379> quit
redis-cli –tls –cacert /etc/redis/tls/ca.crt -p 26379
从第一个副本(redissentinel-tokyo2)进行连接测试。
使用-h选项来切换主机。
redis-cli -h redissentinel-tokyo2 --tls --cacert /etc/redis/tls/ca.crt
Ping正在工作正常。角色为slave被显示。
root@redissentinel-tokyo1:~# redis-cli -h redissentinel-tokyo2 --tls --cacert /etc/redis/tls/ca.crt
redissentinel-tokyo2:6379> ping
PONG
redissentinel-tokyo2:6379> info replication
# Replication
role:slave
master_host:192.168.198.87
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:429878
slave_repl_offset:429878
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:fac9e97e4769636aa327dbdf17c54bbfe8e2a5dc
master_replid2:e545c6cdcac628dbf0851c2521c3c8efa6b9df07
master_repl_offset:429878
second_repl_offset:5818
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:68
repl_backlog_histlen:429811
redissentinel-tokyo2:6379>
操作数据。可读(get)但无法写(set)。由于Redis副本服务器无法写入,因此可以将其用作只读服务。
redissentinel-tokyo2:6379> get scott
"tiger"
redissentinel-tokyo2:6379> set scott lion
(error) READONLY You can't write against a read only replica.
redissentinel-tokyo2:6379>
从第二个复制品(redissentinel-tokyo3)进行连接测试。
使用 -h 选项切换主机。
redis-cli -h redissentinel-tokyo3 --tls --cacert /etc/redis/tls/ca.crt
“ping正在运行,并显示角色为slave”
root@redissentinel-tokyo1:~# redis-cli -h redissentinel-tokyo3 --tls --cacert /etc/redis/tls/ca.crt
redissentinel-tokyo3:6379> ping
PONG
redissentinel-tokyo3:6379> info replication
# Replication
role:slave
master_host:192.168.198.87
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:445061
slave_repl_offset:445061
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:fac9e97e4769636aa327dbdf17c54bbfe8e2a5dc
master_replid2:e545c6cdcac628dbf0851c2521c3c8efa6b9df07
master_repl_offset:445061
second_repl_offset:5818
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:68
repl_backlog_histlen:444994
我执行数据操作。可以读取数据,但不可以写入数据。
redissentinel-tokyo3:6379> get scott
"tiger"
redissentinel-tokyo3:6379> set scott tiger3
(error) READONLY You can't write against a read only replica.
文件结构
我将检查Redis的配置文件和日志文件。
/redis的/etc/
root@redissentinel-tokyo1:~# cd /etc/redis
root@redissentinel-tokyo1:/etc/redis# ls -l
total 252
-rw-r----- 1 redis redis 107058 Jun 29 14:06 redis.conf
-rw-r--r-- 1 redis redis 106589 Dec 16 2022 redis.conf.bak
-rw-r----- 1 redis redis 15699 Jun 29 14:07 sentinel.conf
-rw-r--r-- 1 redis redis 14894 Jun 29 14:03 sentinel.conf.bak
drwxr-xr-x 2 redis redis 4096 Jun 29 14:06 tls
root@redissentinel-tokyo1:/etc/redis#
在 Redis 复制页面中,提到了关于副本的 maxmemory 的注意事项。副本会忽略 maxmemory,并且被初步设计为确保主从一致性。默认情况下,副本不会进行 evict 操作,因此可能会使用比 maxmemory 设置的内存更多(这是因为副本可能具有较大的缓冲区或在数据结构中使用更多的内存)。请监视副本,并确保副本有足够的内存,以防止在主节点达到设置的 maxmemory 之前陷入内存不足的状态。
要更改此操作,请确保复制品不会忽略maxmemory。使用的配置指令如下:
replica-ignore-maxmemory no
您可以在redis-cli中查看当前设置。
root@redisclient:~# redis-cli -h redissentinel-tokyo1 --tls --cacert redissentinel-tokyo_ca.crt
redissentinel-tokyo1:6379> config get replica-ignore-maxmemory
1) "replica-ignore-maxmemory"
2) "yes"
/ var / log / redis /
root@redissentinel-tokyo1:/etc/redis# cd /var/log/redis
root@redissentinel-tokyo1:/var/log/redis# ls -l
total 12
-rw-rw---- 1 redis adm 3824 Jun 29 14:07 redis-sentinel.log
-rw-rw---- 1 redis adm 7620 Jun 29 14:29 redis-server.log
流程
Redis服务器
root@redissentinel-tokyo1:/var/log/redis# lsof +c 15 -i :6379 | grep redis-server
redis-server 21223 redis 6u IPv4 88791 0t0 TCP localhost:redis (LISTEN)
redis-server 21223 redis 7u IPv6 88792 0t0 TCP localhost:redis (LISTEN)
redis-server 21223 redis 8u IPv4 88793 0t0 TCP redissentinel-tokyo1:redis (LISTEN)
redis-server 21223 redis 9u IPv4 88970 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo1:56444 (ESTABLISHED)
redis-server 21223 redis 10u IPv4 88985 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo1:56458 (ESTABLISHED)
redis-server 21223 redis 11u IPv4 88986 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo3:38680 (ESTABLISHED)
redis-server 21223 redis 12u IPv4 88988 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo2:57826 (ESTABLISHED)
redis-server 21223 redis 13u IPv4 88993 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo3:38692 (ESTABLISHED)
redis-server 21223 redis 14u IPv4 88995 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo2:35624 (ESTABLISHED)
redis-server 21223 redis 15u IPv4 88996 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo2:35634 (ESTABLISHED)
redis-server 21223 redis 16u IPv4 89541 0t0 TCP redissentinel-tokyo1:redis->redissentinel-tokyo3:38696 (ESTABLISHED)
哨兵模式
root@redissentinel-tokyo1:/etc/redis# lsof +c 15 -i :26379
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
redis-sentinel 21283 redis 6u IPv4 88959 0t0 TCP localhost:26379 (LISTEN)
redis-sentinel 21283 redis 7u IPv6 88960 0t0 TCP localhost:26379 (LISTEN)
redis-sentinel 21283 redis 8u IPv4 88961 0t0 TCP redissentinel-tokyo1:26379 (LISTEN)
redis-sentinel 21283 redis 15u IPv4 88981 0t0 TCP redissentinel-tokyo1:54848->redissentinel-tokyo3:26379 (ESTABLISHED)
redis-sentinel 21283 redis 16u IPv4 88982 0t0 TCP redissentinel-tokyo1:60110->redissentinel-tokyo2:26379 (ESTABLISHED)
redis-sentinel 21283 redis 17u IPv4 89475 0t0 TCP redissentinel-tokyo1:26379->redissentinel-tokyo3:60696 (ESTABLISHED)
redis-sentinel 21283 redis 18u IPv4 89477 0t0 TCP redissentinel-tokyo1:26379->redissentinel-tokyo2:57536 (ESTABLISHED)
确认服务自动启动。
root@redissentinel-tokyo1:~# systemctl is-enabled redis-server
disabled
root@redissentinel-tokyo1:~# systemctl is-enabled redis-sentinel
disabled
在服务器停止时需要手动启动,为了实现自动启动,请采取以下步骤。
root@redissentinel-tokyo1:~# systemctl enabled redis-server
root@redissentinel-tokyo1:~# systemctl enabled redis-sentinel
Redis客户端的设定
我会进行必要的更新。
apt update && apt upgrade
将 Redis 服务器的 IP 地址添加到主机文件中,然后准备使用主机名来运行 redis-cli。
# Redis
192.168.198.87 redissentinel-tokyo1
192.168.198.103 redissentinel-tokyo2
192.168.198.112 redissentinel-tokyo3
# END redis servers
我会进行 ping 测试以确认连通性。
root@redisclient:~# ping redissentinel-tokyo1
PING redissentinel-tokyo1 (192.168.198.87) 56(84) bytes of data.
64 bytes from redissentinel-tokyo1 (192.168.198.87): icmp_seq=1 ttl=60 time=0.428 ms
64 bytes from redissentinel-tokyo1 (192.168.198.87): icmp_seq=2 ttl=60 time=0.569 ms
复制 Redis Server 的 /etc/redis/tls/ca.crt 文件,然后将其复制到 Client 的 Linode 服务器上。在使用 redis-cli 时,需要使用相同的证书信息。
root@redissentinel-tokyo1:~# cat /etc/redis/tls/ca.crt
安装 redis-cli。
apt install redis-tools
我尝试使用redis-cli进行连接。
root@redisclient:~# redis-cli -h redissentinel-tokyo1 --tls --cacert redissentinel-tokyo_ca.crt
Could not connect to Redis at redissentinel-tokyo1:6379: No route to host
由于Redis Sentinel服务器上安装了firewalld,因此无法连接到主机。因此,需要将客户端的私有IP地址注册到firewalld中。
获取私有IP地址。IP地址为192.168.139.199。
root@redisclient:~# ip -4 a show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
inet {Public_IP}/24 brd XXX.XXX.XXX.XXX scope global eth0
valid_lft forever preferred_lft forever
inet 192.168.139.199/17 brd 192.168.255.255 scope global eth0
valid_lft forever preferred_lft forever
将获取到的私有IP设置到运行在Redis服务器上的firewalld中。
防火墙的设置
登录 Redis Master 服务器。确认firewalld已经启动。
root@redissentinel-tokyo1:/etc/firewalld# ps auxw|egrep firewalld
root 20936 0.0 1.9 128280 39212 ? Ssl Jun29 0:00 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid
在中文中,您可以使用firewall-cmd来确认firewalld。
root@redissentinel-tokyo1:/etc/firewalld# firewall-cmd -V
1.1.1
root@redissentinel-tokyo1:/etc/firewalld# firewall-cmd --state
running
确认有效的区域设置。
root@redissentinel-tokyo1:/etc/firewalld# firewall-cmd --get-active-zone
internal
sources: 192.168.198.87 192.168.198.103 192.168.198.112
可以看到内部区域的设置已启用。在其中注册了 Redis Sentinel 服务器的公共 IP 地址。
防火墙的设置文件位于 /etc/firewalld/ 目录下。
root@redissentinel-tokyo1:/etc/firewalld# pwd
/etc/firewalld
root@redissentinel-tokyo1:/etc/firewalld# ls -l
total 32
-rw-r--r-- 1 root root 2485 Jun 29 14:03 firewalld.conf
drwxr-xr-x 2 root root 4096 Mar 28 2022 helpers
drwxr-xr-x 2 root root 4096 Mar 28 2022 icmptypes
drwxr-xr-x 2 root root 4096 Mar 28 2022 ipsets
-rw-r--r-- 1 root root 268 Mar 28 2022 lockdown-whitelist.xml
drwxr-xr-x 2 root root 4096 Mar 28 2022 policies
drwxr-xr-x 2 root root 4096 Mar 28 2022 services
drwxr-xr-x 2 root root 4096 Jun 29 14:04 zones
在 “zones” 文件夹下面有个 “internal.xml” 文件。
root@redissentinel-tokyo1:/etc/firewalld# cd zones
root@redissentinel-tokyo1:/etc/firewalld/zones# ls
internal.xml internal.xml.old
文件中注册了Redis Sentinel服务器的私有IP
root@redissentinel-tokyo1:/etc/firewalld/zones#cat internal.xml
<?xml version="1.0" encoding="utf-8"?>
<zone>
<short>Internal</short>
<description>For use on internal networks. You mostly trust the other computers on the networks to not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"/>
<service name="mdns"/>
<service name="samba-client"/>
<service name="dhcpv6-client"/>
<service name="redis"/>
<service name="redis-sentinel"/>
<source address="192.168.198.87"/>
<source address="192.168.198.103"/>
<source address="192.168.198.112"/>
<forward/>
</zone>
我要加上以下的内容。
<source address="192.168.139.199"/>
重新启动防火墙。
firewall-cmd --reload
我会确认状态。
root@redissentinel-tokyo1:/etc/firewalld/zones# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-06-30 08:59:35 UTC; 24s ago
Docs: man:firewalld(1)
Main PID: 29722 (firewalld)
Tasks: 2 (limit: 2234)
Memory: 21.7M
CPU: 958ms
CGroup: /system.slice/firewalld.service
└─29722 /usr/bin/python3 /usr/sbin/firewalld --nofork --nopid
Jun 30 08:59:35 redissentinel-tokyo1 systemd[1]: Starting firewalld - dynamic firewall daemon...
Jun 30 08:59:35 redissentinel-tokyo1 systemd[1]: Started firewalld - dynamic firewall daemon.
再次从Redis客户端进行连接。
root@redisclient:~# redis-cli -h redissentinel-tokyo1 --tls --cacert redissentinel-tokyo_ca.crt
redissentinel-tokyo1:6379>
没有显示错误消息。可以看到 firewalld 的设置已经被启用。
redissentinel-tokyo1:6379> ping
(error) NOAUTH Authentication required.
Ping命令出现了认证错误。这是因为忘记设置REDISCLI_AUTH。请配置后再次尝试。
root@redisclient:~# export REDISCLI_AUTH='REDISのパスワードを設定してください'
root@redisclient:~# redis-cli -h redissentinel-tokyo1 --tls --cacert redissentinel-tokyo_ca.crt
redissentinel-tokyo1:6379> ping
PONG
读取和写入成功。
redissentinel-tokyo1:6379> get scott
"tiger"
redissentinel-tokyo1:6379> set scott dixon
OK
redissentinel-tokyo1:6379> get scott
"dixon"
您可以使用role命令来重新确认自己是否是主服务器。
redissentinel-tokyo1:6379> role
1) "master"
2) (integer) 14510424
3) 1) 1) "192.168.198.112"
2) "6379"
3) "14510424"
2) 1) "192.168.198.103"
2) "6379"
3) "14510424"
在另外两台复制服务器上设置和重新启动 firewalld。
如果最终能够与所有服务器连接,那就是成功。
root@redisclient:~# redis-cli -h redissentinel-tokyo2 --tls --cacert redissentinel-tokyo_ca.crt
redissentinel-tokyo2:6379> ping
PONG
redissentinel-tokyo2:6379> get scott
"dixon"
redissentinel-tokyo2:6379> quit
root@redisclient:~# redis-cli -h redissentinel-tokyo3 --tls --cacert redissentinel-tokyo_ca.crt
redissentinel-tokyo3:6379> ping
PONG
redissentinel-tokyo3:6379> get scott
"dixon"
总结
使用Akamai的云计算服务,可以轻松构建Redis Sentinel集群,并能够从另一台服务器访问该应用程序。还发现可以通过firewalld进行访问控制。