我正在开发一款多人游戏,该游戏有一个类似大厅的区域,玩家可以选择要进入的“区域”。大厅网关由 PHP 提供支持,而实际的游戏玩法则由一台或多台 Java 服务器处理。数据存储是MySQL。
幸福之路:
玩家选择一个区域并告诉大厅他想进入。
大厅检查这是否可以,包括检查该扇区中是否有太多玩家(将该扇区的扇区分配中的条目计数与该扇区的 max_players 值进行比较)。
玩家被添加到扇区分配表中,将他与扇区配对。玩家客户端收到一个密码,可以让他连接到适当的游戏服务器。
比赛条件:
如果两个玩家几乎同时请求访问同一扇区,我可以想象一种情况,他们都被添加,因为在他们的检查开始时有一个空闲空间并且超出了最大玩家数。
最好的解决方案是在扇区分配上锁定表吗?还有其他选择吗?
通常,此类并发问题的解决方案涉及事务和乐观锁定:当您更新计数器时,添加一个where
子句检查旧值并计算更新的行数。
v = select value from counter where id=x.
update counter set value = v+1 where value = v and id=x
如果计数器同时更新,则更新不会更改任何行——因此您知道必须回滚并再次尝试该事务。
一个问题是它可能会导致高争论,只有少数交易成功,很多交易失败。
那么坚持下去可能会更好悲观锁,首先锁定该行,然后更新它。但只有基准才能告诉你。
EDIT
如果您使用没有乐观锁定的事务,则可能会发生以下情况。
Max authorized = 50. Current value = 49.
T1: start tx, read value --> 49
T2: start tx, read value --> 49
T1: update value --> 50, acquire a row lock
T1: commits --> release the lock
T2: update value --> 50, acquire a row lock
T2: commits --> release the lock
两次交易都成功,值都是50,但是存在不一致的情况。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)