【问题标题】:Game player matching algorithm (System Design)玩家匹配算法(系统设计)
【发布时间】:2021-08-23 16:13:09
【问题描述】:

假设我们要设计一个国际象棋游戏平台,我们的用户群约为 5000 万。每当有玩家来到我们的平台下棋时,我们都会随机分配一名与对手评分几乎相同的玩家。每个玩家都有 4 个等级等级 [Easy、Medium、Hard、Expert]。

我的方法是将所有用户保留在 Redis 缓存中(假设所有用户/船只都处于活动状态并等待对手),因此我们将数据保存为以下格式:

"chess:easy" : [u1, u2, u3]
"chess:medium" : [u4, u5, u6]

所以当一个用户来的时候,我会从缓存中删除一个用户并分配。

For example: u7 (easy) wants to play chess games then his opponent will be u1(easy).

但这不会给 并发请求 造成问题,因为我们读取然后从 Redis 列表中删除将阻塞?

任何人都可以提出一个更好的方法来使用或不使用缓存吗?

【问题讨论】:

    标签: redis concurrency system-design


    【解决方案1】:

    但这不会对并发请求造成问题,因为我们读取然后从 Redis 列表中删除将阻塞?

    不,因为 Redis 在 it performs write 时是单线程的,但是假设 5000 万用户在国际象棋级别上平等分布,您将获得 4 个列表,每个难度一个,长度为 1250 万

    操作列表可能会非常复杂,因为使用 [LPOP][1] 选择用户并将其删除具有O(N) 的复杂性,并且最后一个用户可能会等待很长时间才能找到对手。

    我认为您应该旨在使用HASH 数据结构并将用户拆分为different databases

    • db0:简单
    • db1:中等
    • db2:硬
    • db3:专家

    这样你就可以用HSET <USERID> status "ready to play"存储想玩的用户,然后利用RANDOMKEY命令选择对手,用HDEL <KEY RETURNED BY RANDOM> status删除。

    这样做,您将只执行命令O(1),提供快速可靠的匹配系统,您可以使用redis pipeling 功能进一步优化。

    注意:如果您设置并散列每个难度级别并将多个fields 添加到散列中,由于HDEL 命令,您将达到O(N) 复杂度! [1]:https://redis.io/commands/lpop

    任何人都可以提出一个更好的方法来使用或不使用缓存吗?

    您可以使用许多算法,例如:

    但这取决于您希望为客户实现的用户体验。 您可以探索gamedev.stackexchange.com community

    【讨论】:

      猜你喜欢
      • 2023-03-22
      • 1970-01-01
      • 2015-12-21
      • 2015-03-01
      • 2021-07-28
      • 2019-05-20
      • 2014-03-16
      • 1970-01-01
      • 2016-07-19
      相关资源
      最近更新 更多