关于分布式系统一致性问题的思考

今天游戏出了一个BUG,复盘一下。这是一个分布式背包系统,A玩家和B玩家共享着一个背包。A玩家和B玩家的角色背包系统在同一个进程里,而共享背包系统在另一个进程(很可能还是另一台物理机)。因此操作背包就是一个相对耗时的操作。

比如想要从角色背包里面放物品到共享背包,就需要经过这样的流程(可能的设计):

客户端开始发起请求
[进程1] step1: 角色背包判断物品足够
	[进程2] step2: 共享背包放入,并返回是否放入成功
		[进程1] step3: 角色背包消耗物品,并返回是否消耗成功
			[进程2] step4: 如果角色背包消耗失败,则将刚放入的物品删除

这里的设计可能有一致性问题,有两种情况会破坏一致性:

  1. 进程连接断开
  2. 客户端短时间内发起多次请求

情况1是一种异常情况,因为连接断开无法预知,因此处理这种异常我觉得还是很难办的,因此处理方式是对每一步加操作日志,然后就不管了(听闻有一种技术是通过日志恢复数据的,但暂时不考虑这样的操作)。

情况2则是应当妥善对待的,系统必须处理可重入的问题,当step3还没有完成时,step1不可以接受新的请求。解决之道是在step1处加锁,在step3结束后解锁。否则第二次进入step1时仍旧会判断成功并发起后续的请求,这是一种不一致的情况,很难预料后面会发生什么,正确性就要依赖后面代码的逻辑了。

做个总结:在处理一致性问题上,具体问题具体分析,由于分布式系统的问题,一个请求可能会经过多次进程间的转发,而在一个请求还没有正常走完流程时,需要处理再次被请求时的重入问题。

原文地址:https://www.cnblogs.com/demon90s/p/15593903.html