使用 redis 实现 5 万人同服的“相位技术” - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gantleman
V2EX    推广

使用 redis 实现 5 万人同服的“相位技术”

  •  
  •   gantleman 2020-08-03 16:29:03 +08:00 5449 次点击
    这是一个创建于 1961 天前的主题,其中的信息可能已经有所发展或是发生改变。

    完整文章链接 zhuanlan.zhihu.com/p/166347236

    魔兽世界和 EVE 服务器能够同时支持 5 万人在线的技术肯定让很多人流口水吧。今天我用 redis 来模拟实现“相位技术”。所谓“相位技术”就是将服务器分为多个并行的空间。是对传统分割成多个地图场景技术的升级。这个技术通过创建多个并行时空的概念。将多个时空分配到不同的服务器。在客户端请求数据时再将多个时空的数据整合在一起。这样理论上就可以将地图场景再次无限分割。所以理论上使用“相位技术”的服务器承载人数可以达到非常恐怖的 5 万人。

    传统的一个地图一个服务器的做法。如果玩家过多就会大量消耗服务器 CPU 资源。直到 CPU 资源耗尽达到服务器人数上限。因为所有逻辑运算都拥挤在一个线程。这种多个功能间资源抢夺的现象会非常明显。而其中玩家移动是最消耗资源的功能。在每一帧中移动的数据都需要同时广播给其他的玩家。这样其他的玩家才能看到这个玩家在移动。

    如果屏幕内有1千个玩家,哪么就需要广播1千次。相当于每次移动的数据都放大了1千倍。而移动同步的频率通常在每秒1次到60次。同步频率越高在客户端表现越细腻。如果每秒同步频率是1次,哪么每个用户每秒钟就要发送一次千人的广播。1千个用户在服务器一共要发送1百万次的同步信息。也就是说移动同步信息如果不加限制,哪么将会成指数级别的增加。

    关注 surparallel.org 获得更多有趣的并行知识。

    20 条回复    2020-08-04 20:38:53 +08:00
    smallpython
        1
    smallpython  
       2020-08-03 18:12:28 +08:00
    虽然说得很厉害, 但是我玩魔兽有时候捡个任务物品 10 秒钟
    gantleman
        2
    gantleman  
    OP
       2020-08-03 18:23:44 +08:00
    @smallpython 魔兽的服务器是商业秘密,不清楚具体实现方式。如果请我帮忙诊断,报销来回车费,我可以考虑帮他们看看。嘿嘿
    huntcool001
        3
    huntcool001  
       2020-08-04 00:12:53 +08:00
    "1 万人以每秒 60 帧的速度向 redis 提交数据。每秒钟将会达到 60 万次提交"

    一个玩家的位置,真的有必要一秒更新 60 次? 移动的时候客户端再更新不行吗
    gantleman
        4
    gantleman  
    OP
       2020-08-04 05:37:58 +08:00
    @huntcool001 也可以每秒提交一次,但这样角色的动作就会看起来不自然。
    opengps
        5
    opengps  
       2020-08-04 05:49:42 +08:00
    这个模拟有个非常大的差异:单机应用跟集群应用的区别
    opengps
        6
    opengps  
       2020-08-04 05:52:09 +08:00   1
    服务器一旦集群应用后,本身也会损失一定的性能,所以文中那种总数除以单机的承载总量的做法有点理想化。实际引用中需要额外追加一定量的机器
    ArchiTech
        7
    ArchiTech  
       2020-08-04 06:43:56 +08:00   2
    很多游戏的移动不需要每帧或者每秒和服务器沟通,一个常见的做法是当客户端的用户点击一个新位置,比如要从( 0,0 )移动到( 20,30 )这个位置,客户端用 A*算法可以算出移动路径然后直接开始移动,服务器端也有相同的 A*算法会得出完全一致的结果,所以服务器端只要做两件事:一是确认一下这个路径是否可行(以免客户端被恶意篡改了,比如玩家作弊穿墙);二是把目的地的坐标广播一下就好了,中间的路径就不需要广播了。

    https://www.dynetisgames.com/2017/03/19/client-updates-phaser-quest/

    这篇文章也讲了延时如何补偿。
    gantleman
        8
    gantleman  
    OP
       2020-08-04 09:52:00 +08:00   1
    @ArchiTech 有路径的情况下会好些,因为路径算法本身也是吃 cpu 。相位技术的本质就是对 cpu 的分配。是用 io 换效率的方法。空间定位是所有模拟环境的的基础,包括现实中车船飞机的调度,人员定位协作等。并不局限于游戏。
    mattx
        9
    mattx  
       2020-08-04 09:57:04 +08:00   1
    楼主是没做过游戏么,还是来钓鱼的,你最后那个估算简直搞笑?
    1 一般游戏服务器不要 60 帧吧?普通 mmo 10 帧,fps 30 估计就可以了
    2 这种位置信息为什么一定要放 redis 里面,应该是作为玩家信息一部分放内存就好了
    3 为啥估算服务器只有 redis,不要考虑 cpu 等负载情况
    4 魔兽世界以前版本主要是支持 几个无缝大世界,一个世界里面可以承载很多人,后面版本又做了 大世界的负载均衡吧
    5 xx 同服 不是件很难的事情,因为可能包含很多场景,主要还是一个场景最多可以有多少人在一起,并且地图无缝

    还是去看实际的工程吧,trinitycore 之类的。
    des
        10
    des  
       2020-08-04 10:06:12 +08:00
    并不能“无限分割”,分割太细就会有很多进出边界的事件发生
    gantleman
        11
    gantleman  
    OP
       2020-08-04 10:23:23 +08:00
    @mattx 没做过太多游戏,只完整上线过四个游戏。
    1,估值当然要按最高标准来做的。毕竟游戏质量的选择不是技术决定的。60 也好 30 也好是老板决定的。
    2,游戏信息放在哪里要根据性能做选择。因为没有 redis 之前我们也自己开发缓存服务器。如果能保证自己的开发的缓存服务器好于 redis 也可以不用 redis 。在这里 redis 作为通用工具也是事实的标准,作为技术贴容易交流。并且这个技术并不局限于游戏,车辆,船舶,飞机的调度都可能使用。
    3,redis 在这里作为关键节点承担了计算和存储的压力,理论上一个用户可以一个服务,压力比关键节点小很多。
    4,wow 的相位技术公布很久了,可能你对这方面关注不多吧。
    5,这篇文章讨论的是同服也是同场景的问题,因为同服就意味着玩家可能会集中到 1 个地图场景。所以并没有在文章强调同服,同地图还是同场景。也没有限定只能同服不能同地图和同场景。

    以前玩过魔兽模拟器,因为当时模拟器是单线程的性能非常差。自己改写过一个多线程版本可以跑 2 千人同场景。官方后来改名大芒果,再后来的 trinitycore 就没接触了。
    gantleman
        12
    gantleman  
    OP
       2020-08-04 10:27:11 +08:00
    @des 是的,因为相当于用 io 换 cpu 的并行,这里没有计算网络带宽和硬盘极限,每个服务器的封包大小不太好估算。最后的瓶颈可能会出现在内网或外网带宽上。
    Acoolda
        13
    Acoolda  
       2020-08-04 14:06:14 +08:00 via Android
    有必要广播给一千个人吗?只需要广播给在同一个地方的用户就行了吧,其他用户根本不关心
    gantleman
        14
    gantleman  
    OP
       2020-08-04 14:14:11 +08:00
    @Acoolda 是的所以要加限制,使用九宫格,81 宫格,六变格的技术进行过滤。
    gantleman
        15
    gantleman  
    OP
       2020-08-04 18:38:08 +08:00
    @livid 真的要好好夸夸你,谷歌的中文优化做的真棒。第二天就排到了云风 blog 的后面。相位技术 14 年出来的,是魔兽游戏服务器的核心技术。到今天国内都不能出仿制品。无数的大牛在这个技术上折戟沉沙。我就这么免费给大家拿出来了,给各位也卖个热闹好看。各位看过的爷,有钱的捧个钱场,没钱的捧个人场。谢谢您了。
    tcfenix
        16
    tcfenix  
       2020-08-04 19:11:30 +08:00
    老哥你这是真的没开发过游戏了, 我也有几年没摸游戏项目了,如果现在整体趋势有变化请见谅
    1 游戏服务器有很多都是内存数据主要解释,性能又好,又没有网络开销,然后定时落库,所以你应该听说过回档这个事情吧
    2 接触过的游戏项目,redis 主要还是用来放一下临时数据,比如登录态的维护,道理很简单, 游戏服务器就是会追求快,而且用户对游戏上操作响应的忍耐空间是非常小的
    3 你可以参考一下游戏公司招服务端的标准,基本上还是 80% 90%的 c++吧?然后少量的 golang 以及微量的 java
    c++会被怎么用?尤其是祖传的 c++代码...
    4 操作帧跟实际上用户画面帧是完全两回事,举个例子用户可以任何时候向服务器发送操作指令,但是服务器就是可以以每秒 15 帧 或者更少去响应,然后在客户端处理成 30 60 帧,这边 GDC 上面有很多视频,非常建议学习
    sunny352787
        17
    sunny352787  
       2020-08-04 19:22:49 +08:00
    看你的做法我倒是想到了另一种方式,既然已经分了多个游戏服,那么游戏服按类似帧同步的方式每个时间片统一向 redis 提交一次全服的位置同步信息呢?这样对 redis 的压力就没那么大了,只是一次同步的数据会多一点,这个应该也可以优化,毕竟不可能服务器上所有单位都在移动
    sunny352787
        18
    sunny352787  
       2020-08-04 19:25:26 +08:00
    @sunny352787 当然,这只是针对使用 redis 进行位置同步的方式的优化想法,实际上我这边在做玩家同步的时候是有一个单独的位置服务器的,这部分是参照了云风之前的一篇文章
    mattx
        19
    mattx  
       2020-08-04 19:38:07 +08:00
    @gantleman 先说魔兽世界相位技术吧,是巫妖王以后拿来加强融入感的,实际上就是开了一个新的场景,只是因为客户端资源不需要加载(已经在内存)不需要 loading,不是什么高深的技术。
    魔兽世界后期比较关注的技术应该是出现很多地图的跨服玩家,而且主城可以出现很多不同服务器的玩家,应该是把主城也当做位面世界来做了
    你是来蹭流量的吧?“redis 在这里作为关键节点承担了计算和存储的压力,理论上一个用户可以一个服务,压力比关键节点小很多” 这是什么鬼?
    gantleman
        20
    gantleman  
    OP
       2020-08-04 20:38:53 +08:00
    @tcfenix
    @sunny352787
    谢谢,谢谢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5614 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 41ms UTC 02:36 PVG 10:36 LAX 18:36 JFK 21:36
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86