今天游戏出了一个BUG,复盘一下。这是一个分布式背包系统,A玩家和B玩家共享着一个背包。A玩家和B玩家的角色背包系统在同一个进程里,而共享背包系统在另一个进程(很可能还是另一台物理机)。因此操作背包就是一个相对耗时的操作。
比如想要从角色背包里面放物品到共享背包,就需要经过这样的流程(可能的设计):
客户端开始发起请求
[进程1] step1: 角色背包判断物品足够
[进程2] step2: 共享背包放入,并返回是否放入成功
[进程1] step3: 角色背包消耗物品,并返回是否消耗成功
[进程2] step4: 如果角色背包消耗失败,则将刚放入的物品删除
这里的设计可能有一致性问题,有两种情况会破坏一致性:
- 进程连接断开
- 客户端短时间内发起多次请求
情况1是一种异常情况,因为连接断开无法预知,因此处理这种异常我觉得还是很难办的,因此处理方式是对每一步加操作日志,然后就不管了(听闻有一种技术是通过日志恢复数据的,但暂时不考虑这样的操作)。
情况2则是应当妥善对待的,系统必须处理可重入的问题,当step3还没有完成时,step1不可以接受新的请求。解决之道是在step1处加锁,在step3结束后解锁。否则第二次进入step1时仍旧会判断成功并发起后续的请求,这是一种不一致的情况,很难预料后面会发生什么,正确性就要依赖后面代码的逻辑了。
做个总结:在处理一致性问题上,具体问题具体分析,由于分布式系统的问题,一个请求可能会经过多次进程间的转发,而在一个请求还没有正常走完流程时,需要处理再次被请求时的重入问题。