(objectively down,客观下线):超过 quorum 个 sentinel 判定 redis 节点下线。
启动方式:
redis-sentinel /path/to/sentinel.conf
redis-server /path/to/sentinel.conf --sentinel
三个定时任务:
- 每个 Sentinel 节点每秒通过 redis 的
__sentinel__:hello
发布一条消息,宣布自己的存在。同时也订阅来确定其他的 Sentinel 节点。
- 每个 Sentinel 节点每秒对其他 redis 节点执行 ping。确定是否下线。
- 每个 Sentinel 节点每10秒 对 master 和 slave 执行 info,确定 slaves。
配置模拟:
- 配置 Redis 开启主从复制
- 配置 Sentinel 监控主节点
echo "停止当前所有redis-server + redis-sentinel";
ps -x | grep redis | grep -v grep | awk '{print $1}' | xargs -r kill
echo "生成并启动3个 redis 配置";
for port in 6379 6380 6381 ;do
echo -e "daemonize yes\nport $port\npidfile /var/run/redis-$port.pid\nlogfile /var/log/redis/redis-$port.log\n" > /etc/redis/redis-$port.conf
if [ $port != 6379 ];then
echo "slaveof 127.0.0.1 6379" >> /etc/redis/redis-$port.conf
fi
redis-server /etc/redis/redis-$port.conf
done
echo "生成并启动3个 redis-sentinel 配置";
for port in 26379 26380 26381 ;do
echo -e "daemonize yes\nport $port\ndir /tmp\nsentinel monitor mymaster 127.0.0.1 6379 2\nsentinel down-after-milliseconds mymaster 3000\nsentinel parallel-syncs mymaster 1\nsentinel failover-timeout mymaster 60000\nlogfile /var/log/redis/sentinel-$port.log\n" > /etc/redis/redis-sentinel-$port.conf
redis-sentinel /etc/redis/redis-sentinel-$port.conf
done
echo "结束";
常用的channel:
- +switch-master:切换主节点
- +convert-to-slave:切换从节点
- +sdown:主观下线
.NET Core环境开发:
dotnet add package StackExchange.Redis
var options = new ConfigurationOptions()
{
CommandMap = CommandMap.Sentinel,
EndPoints = { { "192.168.0.51", 26379}, {"192.168.0.51", 26381}, {"192.168.0.51", 26380} },
AllowAdmin = true,
TieBreaker = "",
ServiceName = "mymaster",
SyncTimeout = 5000
};
var sentinelConn = ConnectionMultiplexer.Connect(options);
var master = sentinelConn.GetServer("192.168.0.51",26381).SentinelGetMasterAddressByName("mymaster");
// ...
var conn = ConnectionMultiplexer.Connect(master);
sentinelConn.GetSubscriber().Subscribe("+switch-master", (channel, message) =>
{
// mymaster 192.168.0.51 6380 192.168.0.51 6381
Console.WriteLine((string)message);
// ...
conn = ConnectionMultiplexer.Connect(ip);
conn.GetDatabase().StringSet("hello","故障切换后值");
});
sentinelConn.GetSubscriber().Subscribe("+convert-to-slave", (channel, message) =>
{
// slave 192.168.0.51:6379 192.168.0.51 6379 @ mymaster 192.168.0.51 6380
Console.WriteLine((string)message);
});
conn.GetDatabase().StringSet("hello","原始值");
注意:
- 所有Sentinel和Redis不能在同一个节点
Redis Cluster
实际上大部分场景下,Redis Sentinel已经足够好。请根据实际情况采用 Redis Cluster。
Redis Cluster 采用虚拟槽分区方式(16384个虚拟槽)。
原因:
- 需要更高的qps(超过 10w/s)
- 需要更高的数据量(超过 500G)
- 需要更高的带宽(超过 1000M)
常用命令:
redis-cli -h localhost -p 6382 cluster info
:查看集群基本信息
redis-cli -h localhost -p 6382 cluster slots
:查看集群slot信息
redis-cli -h localhost -p 6382 cluster nodes
:查看集群node信息
redis-cli -c
:move自动跳转执行
yum install -y redis-trib
:官方提供了基于 ruby 的工具方便部署
搭建 Cluster 过程:
- 配置
cluster-enabled:yes
cluster-node-timeout 15000
cluster-require-full-coverage no
cluster-config-file node-${port}.conf
- meet
redis-cli cluster meet ip port
- 分配槽(0-1638