优化数据存储

优化匹配队列

不知道童鞋们有没有发现我们的游戏现在有一个问题,就是当某个player_id发起匹配后,一直在匹配中,这时候刷新了网页重新进入游戏,在还没有按匹配按钮的时候,如果服务端匹配成功了,就会自动进入到游戏。

这是因为我们的匹配队列现在用的是一个List结构,当客户端连接断开后,并没有把player_id弹出。而且目前的逻辑也没有做player_id唯一性检测,有可能匹配队列中会存在重复的player_id

解决这个问题的办法有很多,赵童鞋选择的是将List改为Set

做题时间

  1. 修改DataCenter中匹配队列的数据结构为Set
  2. 增加删除匹配队列中某个player_id的方法,当客户端断开时调用该方法删除玩家。

DataCenter类:

  1. <?php
  2. ...
  3. class DataCenter
  4. {
  5. ...
  6. public static function getPlayerWaitListLen()
  7. {
  8. $key = self::PREFIX_KEY . ":player_wait_list";
  9. return self::redis()->sCard($key);
  10. }
  11. public static function pushPlayerToWaitList($playerId)
  12. {
  13. $key = self::PREFIX_KEY . ":player_wait_list";
  14. self::redis()->sAdd($key, $playerId);
  15. }
  16. public static function popPlayerFromWaitList()
  17. {
  18. $key = self::PREFIX_KEY . ":player_wait_list";
  19. return self::redis()->sPop($key);
  20. }
  21. public static function delPlayerFromWaitList($playerId)
  22. {
  23. $key = self::PREFIX_KEY . ":player_wait_list";
  24. self::redis()->sRem($key, $playerId);
  25. }
  26. ...
  27. public static function delPlayerInfo($playerFd)
  28. {
  29. ...
  30. self::delPlayerFromWaitList($playerId);
  31. }
  32. ...
  33. }

得益于我们对key的良好管理,并不需要修改Logic中的代码,仅仅是改了一下Redis的调用方法就解决了。

多个Key合并

如果童鞋们在开发中时常观察RedisKey值的话,就会发现随着游戏的开发,里面的Key越来越多了。

  1. 127.0.0.1:6379> keys *
  2. 1) "game:player_room_id:player_869"
  3. 2) "game:player_room_id:player_141"
  4. 3) "game:player_room_id:player_853"
  5. 4) "game:player_room_id:player_253"
  6. 5) "game:player_rank"
  7. 6) "game:online_player"
  8. 7) "game:player_id:105"
  9. 8) "game:player_room_id:player_235"
  10. 9) "game:player_fd:player_964"
  11. 10) "game:player_room_id:player_264"
  12. 11) "game:player_room_id:player_636"
  13. ...

仅仅是随便测试了几下,就会产生一大堆Key值,部分Key还是有着关系的,如player_room_idplayer_fd等,他们都是关于同一个玩家的,我们可以对这一类Key进行合并。

做题时间

  1. 使用Hash结构合并多个Keyplayer_info中。

DataCenter类:

  1. <?php
  2. ...
  3. class DataCenter
  4. {
  5. ...
  6. public static function setPlayerRoomId($playerId, $roomId)
  7. {
  8. $key = self::PREFIX_KEY . ':player_info';
  9. $field = 'room_id:' . $playerId;
  10. self::redis()->hSet($key, $field, $roomId);
  11. }
  12. public static function getPlayerRoomId($playerId)
  13. {
  14. $key = self::PREFIX_KEY . ':player_info';
  15. $field = 'room_id:' . $playerId;
  16. return self::redis()->hGet($key, $field);
  17. }
  18. public static function delPlayerRoomId($playerId)
  19. {
  20. $key = self::PREFIX_KEY . ':player_info';
  21. $field = 'room_id:' . $playerId;
  22. self::redis()->hDel($key, $field);
  23. }
  24. public static function getPlayerFd($playerId)
  25. {
  26. $key = self::PREFIX_KEY . ':player_info';
  27. $field = 'player_fd:' . $playerId;
  28. return self::redis()->hGet($key, $field);
  29. }
  30. public static function setPlayerFd($playerId, $playerFd)
  31. {
  32. $key = self::PREFIX_KEY . ':player_info';
  33. $field = 'player_fd:' . $playerId;
  34. self::redis()->hSet($key, $field, $playerFd);
  35. }
  36. public static function delPlayerFd($playerId)
  37. {
  38. $key = self::PREFIX_KEY . ':player_info';
  39. $field = 'player_fd:' . $playerId;
  40. self::redis()->hDel($key, $field);
  41. }
  42. public static function getPlayerId($playerFd)
  43. {
  44. $key = self::PREFIX_KEY . ':player_info';
  45. $field = 'player_id:' . $playerFd;
  46. return self::redis()->hGet($key, $field);
  47. }
  48. public static function setPlayerId($playerFd, $playerId)
  49. {
  50. $key = self::PREFIX_KEY . ':player_info';
  51. $field = 'player_id:' . $playerFd;
  52. self::redis()->hSet($key, $field, $playerId);
  53. }
  54. public static function delPlayerId($playerFd)
  55. {
  56. $key = self::PREFIX_KEY . ':player_info';
  57. $field = 'player_id:' . $playerFd;
  58. self::redis()->hDel($key, $field);
  59. }
  60. ...
  61. public static function initDataCenter()
  62. {
  63. //清空匹配队列
  64. $key = self::PREFIX_KEY . ':player_wait_list';
  65. self::redis()->del($key);
  66. //清空在线玩家
  67. $key = self::PREFIX_KEY . ':online_player';
  68. self::redis()->del($key);
  69. //清空玩家信息
  70. $key = self::PREFIX_KEY . ':player_info';
  71. self::redis()->del($key);
  72. }
  73. ...
  74. }

重启游戏并进行游玩,我们再来看一下Redis的情况。

  1. 127.0.0.1:6379> keys *
  2. 1) "game:player_info"
  3. 2) "game:player_wait_list"
  4. 3) "game:online_player"

本章对应Github Commit扩展三:优化数据存储