通过 ServiceStack 运行多个 Redis Sentinel

Posted

技术标签:

【中文标题】通过 ServiceStack 运行多个 Redis Sentinel【英文标题】:Running Multiple Redis Sentinels through ServiceStack 【发布时间】:2021-11-09 22:12:28 【问题描述】:

我正在开发一个通过 Servicestack 使用 Redis Sentinel 的项目。项目成立时,最初的开发人员使用 Redis 进行缓存和维护一系列为系统逻辑提供动力的队列。由于性能问题,我们计划启动一个新的 Redis Sentinel 盒子,并在一台服务器上完成缓存和在另一台服务器上完成排队的功能。

我能够对本地实例进行一些小的更改,我必须使用 RedisClient 和 PooledClient 在两个服务器之间拆分它

container.Register<IRedisClientsManager>(c => new RedisManagerPool(redCon, poolConfig));
container.Register<PooledRedisClientManager>(c => new PooledRedisClientManager(redCon2Test));    

container.Register(c => c.Resolve<IRedisClientsManager>().GetClient());
container.Register(c => c.Resolve<PooledRedisClientManager>().GetClient());
 // REDIS CACHE
container.Register(c => c.Resolve<PooledRedisClientManager>().GetCacheClient());

// SESSION
container.Register(c => new SessionFactory(c.Resolve<ICacheClient>()));

// REDIS MQ
container.Register<IMessageService>(c => new RedisMqServer(c.Resolve<IRedisClientsManager>())
    
        DisablePriorityQueues = true,
        DisablePublishingResponses = true,
        RetryCount = 2
    );
container.Register(q => q.Resolve<IMessageService>().MessageFactory);
this.RegisterHandlers(container.Resolve<IMessageService>() as RedisMqServer);

但问题是我没有在我使用的机器上设置 Redis Sentinel,当我尝试将 Sentinel 连接作为 PooledRedis 连接放入时,我在第二次启动时收到编译错误。它可以让我将其转换为 PooledRedisClientManager,但我不确定 Pooled vs Sentinel 是否可以很好地配合使用

if (useSentinel)

    var hosts = redCon.Split(',');
    var sentinel = new RedisSentinel(hosts, masterName)
       
           RedisManagerFactory = CreateRedisManager,
           ScanForOtherSentinels = false,
           SentinelWorkerConnectTimeoutMs = 150,
           OnWorkerError = OnWorkerError,
           OnFailover = OnSentinelFailover,
           OnSentinelMessageReceived = (x, y) => Log.Debug($"MSG: x DETAIL: y")
       ;
    container.Register(c => sentinel.Start());


    var hosts2 = redCon.Split(',');
    var sentinel2 = new RedisSentinel(hosts2, masterName)
       
           RedisManagerFactory = CreatePooledRedisClientManager,
           ScanForOtherSentinels = false,
           SentinelWorkerConnectTimeoutMs = 150,
           OnWorkerError = OnWorkerError,
           OnFailover = OnSentinelFailover,
           OnSentinelMessageReceived = (x, y) => Log.Debug($"MSG: x DETAIL: y")
       ;
    
    container.Register<PooledRedisClientManager>(c => sentinel2.Start());
 

但老实说,我不确定这是否是尝试解决此问题的正确方法。我什至应该使用 Pooled 管理器吗?有没有一种好方法可以在容器中注册两个不同的 Redis Sentinel 服务器并按照我尝试的方式拆分它们?

【问题讨论】:

【参考方案1】:

ServiceStack 仅允许每个 AppHost 1 个 IRedisClientsManager 实现,如果您使用 RedisSentinel,其 .Start() 方法将返回使用 RedisSentinel 配置的预配置 PooledRedisClientManager

如果您希望 RedisMqServer 使用不同的 RedisSentinel 集群,您应该避免在 IOC 中重复 Redis 注册,而直接使用 RedisMqServer 进行配置,例如:

container.Register<IMessageService>(c => new RedisMqServer(sentinel2.Start())

    DisablePriorityQueues = true,
    DisablePublishingResponses = true,
    RetryCount = 2
);

但是,RedisSentinel 通常是 requires 6 nodes 用于设置最小的高可用性配置,将所需的基础设施资源翻倍似乎适得其反,只是为了为 RedisMQ 拥有一个单独的 Sentinel 集群,尤其是在使用 Redis 作为消息传输的负载时与处理消息的计算资源相比,应该可以忽略不计。 MQ 吞吐量是多少?您应该验证 Redis 服务器上的负载是瓶颈,因为它不太可能发生。

我建议避免这种重复的复杂性并使用不同的 RedisMQ 服务器,例如查看 Background MQ 是否是在后台线程中的内存中执行 MQ 请求的选项,如果您需要使用分布式 MQ,请查看 Rabbit MQ 其中专为该任务而构建,与尝试管理 2 个独立的 RedisSentinel 集群配置相比,所需的维护工作要少得多。

【讨论】:

谢谢,现在我正被推向两个 Sentinel 计划,所以一旦他们完成了环境的全部配置,我将尝试一下 RedisMqServer 直接配置的想法。我将此标记为已回答,但如果我以后有任何问题,可能会向您提出建议。 嘿,mythz,关于这个的小更新(和一个简短的问题),我们尝试将缓存服务转移到 Memcached,但我们的值经常超过 1 MB 的限制。是否有内置标志或任何能够轻松压缩进入缓存的内容的东西?我可以在 ServiceStack 上找到的所有压缩信息都针对通过网络传输的内容,而不是进出缓存的内容 @lasernick 不,redis 或缓存客户端没有内置压缩功能,您需要使用IRedisNativeClient 中的原始字节 [] API 自己执行解压缩。 好的,谢谢您的信息

以上是关于通过 ServiceStack 运行多个 Redis Sentinel的主要内容,如果未能解决你的问题,请参考以下文章

如何手动释放servicestack.redis连接池连接

servicestack VueJS 编译失败

Redis ServiceStack 使用事务时如何创建多个序列号

具有多个数据库服务器的 ServiceStack OrmLite

在 Linux / Mono 上运行 ServiceStack 的最佳方式是啥?

在运行时在 ServiceStack.OrmLite 中获取类的表名/避免硬编码表名