当玩家选择与随机对手玩时,我正在制作一个基于回合的游戏,并试图构建匹配功能。当谈到mysql时,我是一个菜鸟,所以我需要一些帮助。
我在考虑这样做:
当玩家选择对抗随机对手时,请检查“waiting_list”表以查看是否有任何对手。
如果没有对手,请将玩家添加到等候名单中。
等候名单上有一个对手,从列表中移除玩家,然后与其他玩家一起开始游戏。
我担心的是,如果我这样做的话,等待名单上的同一名球员是否有机会被几名球员选中。想象一下,如果有100,000名玩家选择了自动匹配功能,那么数据库(phpmyadmin)是否能够很好地处理它?你会如何构建逻辑?
谢谢
答案 0 :(得分:3)
我担心的是,如果我这样做的话,等待名单上的同一名球员是否有机会被几名球员选中。
你用你的观点描述的内容1.)到3.)是一个所谓的商业交易,你在这里有一个原子操作,只能由一个玩家同时执行。
您应该将操作封装到处理它的对象中,因此您的业务逻辑中有一个接口来执行该事务。
然后你需要实现这个交易。事务可以成功或失败,您可以使用返回值或异常处理失败。
交易本身必须确保您的顾虑被删除。这可以通过独占锁定匹配表,进行匹配,删除或将播放器/操作符添加到等待列表并释放锁定来在MySQL中完成。
请参阅12.3.5. LOCK TABLES
and UNLOCK TABLES
SyntaxDocs。
表锁具有性能影响,因为只要表被锁定,其他会话就无法访问它(等待锁被释放)。
因此,保持锁定时间短是明智的。如果事务需要10毫秒,您可以将它与并发活动事务的数量相乘,以便及时表达您的性能:
0.010 seconds * 100 000 transactions = ~ 16.7 minutes
请注意,您不可能拥有10万个并发交易,因为并非所有玩家都会立即匹配。但是,您需要跟踪数字,因为系统可能会在一段时间后停止。
答案 1 :(得分:1)
为了防止单个玩家进入多个游戏,您可以使用“GameIDAssigned”的附加列(如果不存在)进行等待列表,默认为0(或者甚至是PlayAgainstPerson)。
在查询可用于并向许多玩家显示的数据时,记录可能都具有相似的时间戳,但您只需要1.因此,以随机方法选择一个,然后将ID分配给等于时间戳的ID没有分配游戏。如果它回来了1条记录被更新,那就是你的。如果它被分配给其他人,则GameIDAssigned将被填写,从而阻止您第二次分配它。比如...
PersonIDFromWaitingList = SomeValueEvenIfBySQLSubSelect
Update YourWaitingListTable
set GameIDAssigned = SomeCurrentGameIDSequence
where DateTimeStampColumn = ValueWhenOriginallyQueried
AND GameIDAssigned = 0
在没有看到任何其他关于你的游戏结构或表格列的元素的情况下,我现在可以提供更多的内容,但希望你能够得到这个想法。如果一个等待名单的人被同时由多个人分配,则只有第一个获得更新完成的人(当游戏ID分配仍为0时)获胜并且其他所有人试图获得该人将会错过并需要尝试下一个可用...