[转帖]关于一致性哈希算法在游戏服务器端的思考

关于,一致性,哈希,算法,游戏,服务器,端的,思考 · 浏览次数 : 0

小编点评

**a. 新增/减少节点问题** 1. 使用一致性哈希算法来确定要新增或减少的节点。 2. 当新节点连接时,对其进行一致性哈希计算,并将其映射到合适的节点上。 3. 当节点数量变化时,对已经连接的节点进行一致性哈希计算,并更新其节点映射关系。 **b. 整体负载均匀问题** 1. 使用负载均衡算法,例如 Round Robin,将所有节点分配到不同的服务器上。 2. 监控节点负载,并根据负载变化动态调整服务器分配。 3. 使用一致性哈希,在添加或删除节点时,重新分布节点,以保持负载均衡。 **扩展思路** 1. 使用有限负载一致性哈希 (FLSH) 来降低添加/删除节点的影响。 2. 使用动态负载一致性哈希 (DLSH) 来动态调整节点分配。 3. 使用多台服务器的负载均衡器来提高性能。

正文

https://www.jianshu.com/p/b8ae27cf22a9

突然想明白 其实网易的将军令 就是一个一致性哈希的玩法

 

关于一致性哈希算法在游戏服务器端的思考

  1. 需求分析

    • 后端有很多逻辑node节点(not-section binded),节点启动后注册到注册中心
      • node本身有状态,有内存cache,有过期时间
    • 客户端登陆,需要从注册中心分配一个node
      • a. 客户端需要在一段时间内连接固定节点(长连接)。因为内存有状态,最好支持客户端断线一段时间再次连接还是之前的节点
      • b. 节点最好是相对负载均匀的
      • 考虑新增/减少节点(宕机),最好保证a/b两点
  2. 引入一致性hash算法

    • 算法主要参考:dubbo ConsistentHashSelector 并做部分修改

    • 算法测试

      • a. 初始运营服5个,每个服10w注册,即50w注册。后端一个node承载1w,后端初始50个node

        算法步骤

        1. 初始化50w个rid,rid格式 serverId_id,shuffle
        2. build hash ring,replicaNumber(虚拟节点) = 160
        3. 依次遍历shuffle后的rid list,从hash ring select
        4. 看node整体分布情况(最大、最小、平均、标准差)
        5. 不断调整虚拟节点数目

        统计结果展示

        [7743, 8777, 8847, 8932, 8985, 9100, 9185, 9229, 9274, 9308, 9330, 9478, 9625, 9638, 9660, 9697, 9699, 9728, 9748, 9791, 9794, 9847, 9904, 10021, 10053, 10055, 10063, 10073, 10257, 10258, 10263, 10291, 10356, 10374, 10376, 10486, 10519, 10521, 10581, 10620, 10628, 10678, 10719, 10783, 10790, 10837, 10859, 11001, 11120, 12099]
        replica:160 |max:12099|min:7743|mean:10000.0|std:750.9|median:10054.0

        [9142, 9393, 9518, 9525, 9549, 9578, 9626, 9659, 9667, 9690, 9765, 9777, 9811, 9831, 9848, 9850, 9886, 9889, 9909, 9933, 9940, 9958, 9998, 10002, 10007, 10029, 10030, 10050, 10052, 10129, 10152, 10158, 10182, 10184, 10202, 10212, 10213, 10215, 10247, 10265, 10273, 10279, 10297, 10321, 10322, 10342, 10358, 10420, 10456, 10861]

        replica:1280 |max:10861|min:9142|mean:10000.0|std:317.2|median:10018.0

        结论

        1. 在节点不动态变化的情况,算法可以保证同一个rid每次都select到同一个node
        2. 通过调整replicaNumber,可以让node负载相对均匀
        3. 因为rid样本是可确定的,所以可以这种方式不断调整hash ring的参数,来符合实际的负载情况,即是可预测的
          • 如果一个node负载是1w,那么目前会有node overloaded。实际可以考虑将node负载调整为9k
      • b. 从a的结果上看,看似很美好,比较好的满足我们的需求,but 我们还要考虑新增/减少节点的情况

        假设

        1. 让我们问问题先简化一下 因为我们本身是长连接,所以假设之前的50w个rid全部连接到已知的50个node

        2. 需求:准备开始开第6个服,在新增10个node,用来承载10w人,并重建hash ring

        测试输出

        // 这个是已经连接的50个node的数据分布情况,和a的结果一致,也验证了本身一致性hash算法的正确性

        [9142, 9393, 9518, 9525, 9549, 9578, 9626, 9659, 9667, 9690, 9765, 9777, 9811, 9831, 9848, 9850, 9886, 9889, 9909, 9933, 9940, 9958, 9998, 10002, 10007, 10029, 10030, 10050, 10052, 10129, 10152, 10158, 10182, 10184, 10202, 10212, 10213, 10215, 10247, 10265, 10273, 10279, 10297, 10321, 10322, 10342, 10358, 10420, 10456, 10861]

        replica:1280 |max:10861|min:9142|mean:10000.0|std:317.2|median:10018.0

        // 这个是新增10个node后的数据分布情况

        [1499, 1534, 1569, 1652, 1673, 1675, 1684, 1712, 1713, 1723, 10585, 10948, 11119, 11162, 11173, 11177, 11223, 11267, 11270, 11324, 11348, 11404, 11504, 11511, 11530, 11546, 11547, 11569, 11570, 11610, 11631, 11635, 11674, 11681, 11684, 11706, 11742, 11750, 11758, 11769, 11796, 11815, 11842, 11855, 11878, 11908, 11912, 11921, 11933, 11952, 11991, 11996, 12019, 12068, 12068, 12077, 12089, 12157, 12215, 12657]

        replica:1280 |max:12657|min:1499|mean:10000.0|std:3783.8|median:11620.5

        结论

        1. 我们在假设条件成立的情况下,我们期望新增的10w客户端全部负载到新的10个node上。但是从结果上看,其实是负载了整个的60个node上(这个其实也是相对均匀的)。这个和我们预期完全不相符
        2. 从一致性hash的算法实现上看,对于新增/减少节点来说,一定是会有一部分客户端重新分配节点,这个是由算法本身决定的
  3. 继续沿着一致性hash的思路走

    • 主要问题
      • a. 如何解决新增/减少节点,部分客户端select节点变化的问题?
      • b. 如何解决新增节点,整体的负载均匀问题(甚至分配过程中的相对均匀,即不会出现分配过程中某一个node先达到上限,而是整体均衡)?
    • 一些扩展思路
      • 对于a
        • 可以在客户端select到一个节点后,将客户端和节点的映射关系保存下来。客户端断线再连接还是同一个节点。当内存数据过期后,下次再连接,可以再次重新映射
        • 可以在每次客户端断线时,强制刷新一下对应的node内存数据到外部缓存。这样当客户端再次连接时,如果切到了其他的node也没有关系,只不过额外走一次加载流程。不过如果是频繁断线重连的情况下则需要额外注意
      • 对于b
        • 可以引入有限负载一致性哈希,即node有负载的概念。首选还是按照正常的一致性hash算法选择某一个node。不过区别是会判断此node是否overloaded,如果overloaded,则继续从hash ring寻找下一个node,直到未超过负载。引入该算法后,对于2b中的测试来说,新的10w人会被主要分流到新增的10个node上
          • 我目前实现的一个版本是可以设置一个node的负载上限比如9000
          • 不过引入负载后,就需要额外维护负载这个指标。比如客户端内存数据过期后,将客户端所属的node的负载-1
    • 思考
      • 如果我们按照一致性hash的思路实现需求,是可以做的,只不过有不少额外成本。那这样的必要性大吗?
      • 一致性hash最早的例子是用在如memcache,根据key hash到对应的node。而这个应用场合是缓存,即使key没有命中的话(增/减),那么对于应用层来是可以重新从数据库加载的。所以其实应用场合并一定特别适合
      • 对于我们的需求,我们手动实现一个基于负载的类似轮询算法,是不是更简单?
  4. 再换一个思路 假如我们把连接和数据分开呢?

    • 假如我们让客户端不是直接连接后端的node,而是一个网关呢?
    • 网关负责连接,node负责数据
    • 我们有一组网关,网关的数量是固定的(当然也可以在维护时间调整),先通过客户端rid做hash运算到对应的网关(为保证均匀,可以考虑一致性hash)
    • 然后再通过网关和后端node的映射关系得出客户端该路由到那个node上。这样node节点动态变化时,只需要修改路由表中网关和动态node之前的关系即可
    • TODO
      • Consistent Hashing + Distributed Hash Table (Orleans)
  5. ref

与[转帖]关于一致性哈希算法在游戏服务器端的思考相似的内容:

[转帖]关于一致性哈希算法在游戏服务器端的思考

https://www.jianshu.com/p/b8ae27cf22a9 突然想明白 其实网易的将军令 就是一个一致性哈希的玩法 关于一致性哈希算法在游戏服务器端的思考 需求分析 后端有很多逻辑node节点(not-section binded),节点启动后注册到注册中心 node本身有状态,有

[转帖]程序员版本的八荣八耻,爱了

https://juejin.cn/post/7105604721028628511 前言 大家好,我是捡田螺的小男孩。 最近整理了一个关于程序员版本的八荣八耻,还挺有意思的。给大家娱乐一下,哈哈~ 公众号:捡田螺的小男孩 我的github地址,感谢给个star 1. 以接口兼容为荣,以接口裸奔为耻

[转帖]内存池 及 nginx内存池

https://cloud.tencent.com/developer/article/1888241?areaSource=&traceId= 动不动就 32GB 以上内存的服务器真需要关心内存碎片问题吗? 咳咳,这是知乎上的一个议题哈。我看了之后觉得,我不能等明天了,我今天就把nginx的内存池

[转帖]深入学习MySQL事务:ACID特性的实现原理

https://www.cnblogs.com/kismetv/p/10331633.html 事务是MySQL等关系型数据库区别于NoSQL的重要方面,是保证数据一致性的重要手段。本文将首先介绍MySQL事务相关的基础概念,然后介绍事务的ACID特性,并分析其实现原理。 MySQL博大精深,文章疏

[转帖]TiFlash 简介

overview TiFlash 是 TiDB HTAP 形态的关键组件,它是 TiKV 的列存扩展,在提供了良好的隔离性的同时,也兼顾了强一致性。列存副本通过 Raft Learner 协议异步复制,但是在读取的时候通过 Raft 校对索引配合 MVCC 的方式获得 Snapshot Isolat

[转帖]PostgreSQL配置文件--WAL

2022-12-23 3.1 Settings 3.1.1 fsync 字符串 默认: fsync = on 开启后强制把数据同步更新到磁盘,可以保证数据库将在OS或者硬件崩溃的后恢复到一个一致的状态。 虽然关闭,可以提升数据库性能,但无法保证数据库崩溃后数据一致性。 通常情况下需要打开这个参数,除

[转帖]关于SRE方法论的一些笔记

写在前面 阿里系列有一本《云原生操作系统Kubernetes》中作者在前言里讲到Google开源的Kubernetes和《SRE Google运维解密》这本书是剑法和气功的关系换句话讲Kubernetes是术,SRE Google运维解密是道作为云原生基础设施的Kubernetes小伙伴么应该多少有

[转帖]一些关于屁股的想法

作者是 Dante 发布于 2022年3月15日 in 杂项, 职场. 哦,不要想歪了,这里说的屁股,是“屁股决定脑袋”里的屁股。觉得不好听的话,可以翻译成:立场决定观点。 其实我们都是自己屁股的代言人。 不过,我从来也没觉得这个是不好的事情。作为一家公司,一个集体,我们是多元化的,只有其中的每一个

[转帖]关于TIME_WAIT优化

我们先看一下四次挥手过程 # netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' # netstat -tan | awk '{print $6}' | sort | uniq -c 通过此图先说明几个概念: TI

[转帖]关于nginx 反向代理upstream中的 keepalive配置

一、关于nginx upstream 在nginx的模块中,分为3种类型,分别是handler,filter和upstream,其中upstream可以看做一种特殊的handler,它主要用来实现和后端另外的服务器进行通信,由于在nginx中全部都是使用非阻塞,并且是一个流式的处理,所以upstre