ServiceStack.Redis.Sentinel 用法

ServiceStack.Redis.Sentinel Usage

我是 运行 ServiceStack 的许可版本,正在尝试在 Google 云计算上设置哨兵集群。

集群基本上是GCE的点击部署redis解决方案——3台服务器。这是我用来初始化的代码...

var hosts = Settings.Redis.Host.Split(';');
var sentinel = new ServiceStack.Redis.RedisSentinel(hosts, "master");
redis = sentinel.Setup();

container.Register<IRedisClientsManager>(redis);
container.Register<ICacheClient>(redis.GetCacheClient());

客户端工作正常 - 但是一旦我关闭了其中一个 redis 实例,一切都乱七八糟。客户端抱怨无法连接到丢失的实例。此外,即使我重新启动实例 - 它处于只读模式,所以一切仍然失败。一旦你处于这种状态,似乎没有办法恢复...

我是不是做错了什么? RedisSentinal 客户端有什么原因不知道新主人是谁?我给它提供了所有 3 个主机 IP 地址...

您应该只向 RedisSentinel 提供 Redis Sentinel 服务器的主机,因为它从 Sentinel 主机获取其他 master/slave redis 服务器的活动列表。

最近在最新的 v4.0.37 中添加了对 RedisSentinel 的一些更改,现在是 available on MyGet,其中包括额外的日志记录和 Redis Sentinel 事件的回调。新的 v4.0.37 API 看起来像:

var sentinel = new RedisSentinel(sentinelHost, masterName);

启动 RedisSentinel 将连接到 Sentinel 主机和 return 具有活动

的预配置 RedisClientManager(即 redis 连接池)
var redisManager = sentinel.Start();

然后您可以在 IOC 中注册:

container.Register<IRedisClientsManager>(redisManager);

然后 RedisSentinel 应该监听来自 Sentinel 主机的 master/slave 变化并相应地故障转移 redisManager。然后处理池中的现有连接,并为新配置的主机替换为新池。如果再次使用池外的任何活动连接,它们将抛出连接异常,下次从池中检索 RedisClient 时,它将使用新主机进行配置。

回调和日志记录

下面是一个示例,说明如何使用新的回调来检查 RedisServer 事件:

var sentinel = new RedisSentinel(sentinelHost, masterName)
{
    OnFailover = manager => 
    {
        "Redis Managers were Failed Over to new hosts".Print();
    },
    OnWorkerError = ex =>
    {
        "Worker error: {0}".Print(ex);
    },
    OnSentinelMessageReceived = (channel, msg) =>
    {
        "Received '{0}' on channel '{1}' from Sentinel".Print(channel, msg);
    },                
};

也可以通过配置 Logging in ServiceStack:

来启用这些事件的记录
LogManager.LogFactory = new ConsoleLogFactory(debugEnabled:false);

还有一个额外的显式 FailoverToSentinelHosts() 可用于强制 RedisSentinel 重新查找并故障转移到最新的 master/slave 主机,例如:

var sentinelInfo = sentinel.FailoverToSentinelHosts();

新主机在 returned sentinelInfo 中可用:

"Failed over to read/write: {0}, read-only: {1}".Print(
    sentinelInfo.RedisMasters, sentinelInfo.RedisSlaves);