对于 Redis node 的数量 N 理论上需要保持偶数台,一般不少于6个才能保证组成一个闭环的高可用的集群,这也意味着理想状态至少需要6台服务器来承载,但这里个人在架构设计中,往往场景不是很敏感,那么将设计为 N/2台服务器分布,目的是兼顾成本以及折中照顾到主从之间的 HA机制(HA相关可以参照上一篇里提到的部分延伸,这里尽量避免重复性讨论)。 这里要稍微注意的是,对于机器的配对,尽量保证不要在同一台机器上配置过多的Master,否则会严重影响选举,甚至failover被直接拒绝,无法重建。
对于 node 之间的消息交互,每次发送的数据均包含 slot数据和集群基础状态,node越多分发的数据也几近是倍增,这个在上面 Sharding 算法里也表明,那么一方面可以针对 node数量进行控制,另一个则是设置合理的消息发送频率,比如在主要配置 cluster-node-timeout上,适当由默认15秒递增 5/10 秒。但是过度调大 cluster_node_timeout相关设置一定会影响到消息交换的实时性,所以我认为这里可以尝试微调,在大多数本身比较均匀分布数据的场景下适当放宽,这样不会对node检测和选举产生较大影响,同时也间接节约了一定网络IO。
对于数据增长粒度较大的场景,优先控制集群的 node数量,否则同样避免不了一个比较大头的用户指令消耗 和 Gossip维护消息开销(集群内所有 node的ping/pong消息),官方早前就建议控制集群规模不是没有道理的。个人认为真到了需要的场景,必须主动作减法,缩减node数,取而代之使用小的集群来分散业务,而且这也有利于更精确的控制风险和针对性优化。
对于集群的伸缩,如项目中应用较多操作的一般是扩容场景,增加新的node 建议跟集群内的已有 node 配置保持一致,并且在完成 cluster meet 后,需要合理控制划分出的 slot 数,一般没有特殊要求,应该都是均匀化。额外要稍微注意的是,新的 node 务必保证是一个干净的node,否则会造成不必要的拓扑错误(这种是可能会导致数据分布复制严重错乱的),当然新增 node这里也可以借助 redis-trib.rb 或者其他第三方包装的方案来辅助操作。
对于不在当前 node 的键指令查询,默认是只回复重定向转移响应(redirect / moved)给到调用的客户端(这里特指应用程序端),并不负责转发。这是跟单机是完全不同的,所以即使是使用相关的第三方驱动库(比如JAVA的Jedis、和.Net的 StackExchange.Redis)完成程序端的封闭式控制,也仍旧需要权衡数据的热点分散是否足够集中在各自的node中等细节。当然,假如是 hashset等结构,由于Cluster本身的Sharding机制涉及到不可分散负载,倒是无需过多编码实现,也不用担心性能在这里的损耗。
结语
本篇先写到这里,下一篇会继续围绕相关主题尝试扩展阐述。
PS:由于个人能力和经验均有限,自己也在持续学习和实践,文中若有不妥之处,恳请指正。
个人目前备用地址:
社区1:https://yq.aliyun.com/u/autumnbing
社区2:https://www.cnblogs.com/bsfz/
【预留占位:分布式系统之缓存的微观应用经验谈(四)【交互场景篇】