从事游戏开发也有年头了,许多积累下来的知识和经验并没有做很好的梳理。
之前虽然也零零散散写过一点关于挂机和调试的短文,这次写点关于数据同步的东西。
游戏是个低延时,高并发应用。一般为了提供给用户足够好的体验都会把数据库单独放置一台机器,为的是让游戏进程和数据库进程都能得到充足的资源,都能提供优秀的服务。这也产生了一个问题,如何保证数据库的数据和游戏进程中用户本身没有差别。实际上这个问题一直存在不过分别置于两台机器后这个问题被放大了。
程序不会骗人,但计算机这个工业产物却会当机,程序员们也无法保证每次提交的代码不会造成进程突然死亡。某次当机,进程死亡,用户恰恰在上一个瞬间刚刚买了一把武器。那么这把武器到底在数据里有没有反应出来呢?再次重启服务,用户能看到自己买的武器吗?如果数据库里没有,丢失了用户的数据,往下推论我们的进程不是在服务一个人,而是在服务很多人,是不是很多人也丢失了数据,这么多数据里面有没有对用户特别重要的数据?
保证同步最基本的方法,取消多线程的异步,等待数据库更新完成然后再响应用户,分布式存储里称之为强一致性。当然这个方法会增大用户的延时,服务一个用户的时间增长,服务总人数也会下降,吞吐量也会掉下来。如果游戏性允许将用户全集拆成多个子集,增加服务进程数量也可以解决吞吐量的问题。
有强一致性,就有弱一致性。响应用户时不必等待和数据库通信的完毕,把用户的改变写到本地日志文件,等待文件IO完毕即可响应用户。原来负责执行数据库更新的线程现在负责从本地日志文件中读取数据的变更并同同步到数据库。
这个模式和上一个模式相比就是利用本地文件的顺序写来缩短和数据库更新的时间,在保证数据被记录的基础上减小延时。
只要数据的保存在游戏线程或进程之外的系统设计都要解决数据同步这个子模块。但是,但是。事情不是绝对的,我们是要保存用户的数据,但是一个用户所有的数据不是都不能丢失的。这样程序员要做的就简单了,不能丢失的用户数据也就那么几个,全服几千人加起来延时也不是不能忍受的。
最后,梳理一下。
目的:保证低延时且关键数据不丢失
手段:游戏线程或进程保证关键数据顺序写入本地日志,其他数据交由数据服务线程同步到数据库。数据服务线程或进程一次读取一个关键数据日志文件,批量同步到数据库,用事务保证这一批数更新的完整性。更新完毕,在一个记录文件上写入更新到某个点。
之前虽然也零零散散写过一点关于挂机和调试的短文,这次写点关于数据同步的东西。
游戏是个低延时,高并发应用。一般为了提供给用户足够好的体验都会把数据库单独放置一台机器,为的是让游戏进程和数据库进程都能得到充足的资源,都能提供优秀的服务。这也产生了一个问题,如何保证数据库的数据和游戏进程中用户本身没有差别。实际上这个问题一直存在不过分别置于两台机器后这个问题被放大了。
为什么要保证没有差别,因为一旦发生当机,用户的数据和公司在数据库的数据就会不一致,一旦发生撕逼,用户就会流失,基于流量变现的网络服务都会避免这种情况的发生。
程序不会骗人,但计算机这个工业产物却会当机,程序员们也无法保证每次提交的代码不会造成进程突然死亡。某次当机,进程死亡,用户恰恰在上一个瞬间刚刚买了一把武器。那么这把武器到底在数据里有没有反应出来呢?再次重启服务,用户能看到自己买的武器吗?如果数据库里没有,丢失了用户的数据,往下推论我们的进程不是在服务一个人,而是在服务很多人,是不是很多人也丢失了数据,这么多数据里面有没有对用户特别重要的数据?
保证同步最基本的方法,取消多线程的异步,等待数据库更新完成然后再响应用户,分布式存储里称之为强一致性。当然这个方法会增大用户的延时,服务一个用户的时间增长,服务总人数也会下降,吞吐量也会掉下来。如果游戏性允许将用户全集拆成多个子集,增加服务进程数量也可以解决吞吐量的问题。
有强一致性,就有弱一致性。响应用户时不必等待和数据库通信的完毕,把用户的改变写到本地日志文件,等待文件IO完毕即可响应用户。原来负责执行数据库更新的线程现在负责从本地日志文件中读取数据的变更并同同步到数据库。
这个模式和上一个模式相比就是利用本地文件的顺序写来缩短和数据库更新的时间,在保证数据被记录的基础上减小延时。
只要数据的保存在游戏线程或进程之外的系统设计都要解决数据同步这个子模块。但是,但是。事情不是绝对的,我们是要保存用户的数据,但是一个用户所有的数据不是都不能丢失的。这样程序员要做的就简单了,不能丢失的用户数据也就那么几个,全服几千人加起来延时也不是不能忍受的。
最后,梳理一下。
目的:保证低延时且关键数据不丢失
手段:游戏线程或进程保证关键数据顺序写入本地日志,其他数据交由数据服务线程同步到数据库。数据服务线程或进程一次读取一个关键数据日志文件,批量同步到数据库,用事务保证这一批数更新的完整性。更新完毕,在一个记录文件上写入更新到某个点。
过程:1数据库服务当掉。数据库不可用,所有要更新的数据全部顺序写入本地。注意,这里不要和关键数据的本地日志搞混。用户下线把整个用户的的数据dump出来。
同部数据分作线上同步和线下同步。线下同步,在游戏服务停止的情况下,把关键数据日志,变更数据日志,和用户数据dump顺序导入到数据即可,启动游戏服务。线上恢复,保持游戏服务的可用,首先要恢复之前累积的数据,在之前新的数据变更不能直接更新的数据库。新的数据变更也写入日志,变更同步完毕,可以直接写入数据库。