【问题标题】:User ranks: how to do it without SQL?用户行列:没有 SQL 怎么办?
【发布时间】:2013-01-16 15:22:36
【问题描述】:

我正在开发在线游戏的服务器端部分,其中一项任务是计算用户排名。目前它使用 RDBMS 完成,但每次玩家赢得游戏时它都会更新每个用户行。当平均有 20 名玩家在线时,它现在会导致死锁。

我理解这种趋势——当有 1000 名玩家时,数据库解决方案根本行不通。

如何在 Apache/PHP 服务器上实时计算用户排名?有更智能的数据库解决方案吗?

【问题讨论】:

  • 20 个用户时出现死锁?听起来您正在使用 Access。是/否?
  • 一点也不。我正在使用 MySQL,但是当多个用户同时访问数据库时,用户等级更新可能会重叠。我相信这会导致死锁。

标签: php mysql database ranking


【解决方案1】:

您可以将您的排名放在另一个表格中,您每次都TRUNCATE。 已经提出(并回答)了一个类似的问题,可以在这里找到: Best way to update user rankings without killing the server

【讨论】:

  • 很好的解决方案,谢谢。但我想知道,是否有一个根本不使用 RDBMS 的解决方案?使用平衡的 BST 可以轻松解决任务,也许 Apache/PHP 已经准备好了一些东西?
  • 实现了这样的方法,但它现在会产生很多重复的键错误。问题是多个用户可以同时运行排名更新,这会导致查询重叠。似乎解决方案只是将问题转化为另一个问题,但并没有解决它。
  • Sammich 的方法怎么样?
【解决方案2】:

为什么要将排名存储在单独的表中?根据需要存储分数并查询排名,甚至创建视图。您只需更新与单个用户相关的数据,而不是更新整个表,如果您使用 InnoDB 表,则 UPDATE 查询将使用行级锁定,而不是使用 myISAM 获得的表级锁定。

TABLE users
  user_id INT PK
  user_name VARCHAR
  ...

TABLE user_scores
  user_id PK FK
  score INT INDEX
  wins INT INDEX

VIEW v_user_ranks
  SELECT u.user_id, u.user_name, s.score, s.wins
  FROM users u INNER JOIN user_scores s
    ON u.user_id = s.user_id

SELECT *
FROM v_user_ranks
ORDER BY score, wins DESC
LIMIT 10

INSERT INTO user_scores (user_id, score, wins)
  VALUES ($id, $score, $wins)
  ON DUPLICATE KEY UPDATE score=score+$score, wins=wins+$wins

【讨论】:

  • 问题是我需要能够快速检索用户排名(告诉用户他们的旧/新排名并在他们赢得比赛时更改)并且还能够显示用户评分表排序不是按排名,而是按其他类别(例如按字母表)。这就是为什么我需要在每次用户排名发生变化时实现他们。
  • 您的方法是在每次用户赢得游戏时更新整个表格,然后选择以特定方式排序的 X 行。我的方法包括更新 单行,然后以特定顺序选择 X 行。哪个听起来更快?此外,当经常执行涉及整个表的操作时,您永远无法绕过您现在正在解决的表级死锁。
  • 还没有看懂你的方法,抱歉(请您详细说明一下。什么是得分,什么是胜利?用户排名在哪里?
  • @user1065145 scorewins 字段将存储玩家的累积分数和获胜次数,排名将根据结果集中的行索引确定。有种方法可以在结果集中强制输入一个实际数字,但是在程序代码中而不是在查询中这样做更容易、更灵活。
  • 没关系,当您一次只需要获得一个玩家的排名时。如果您同时需要所有这些怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-21
相关资源
最近更新 更多