发明内容
本发明针对Git、SVN控制工具对于新加入的用户想要获取数据,需要下载仓库中的所有数据包括变更记录的问题,提出一种可离线交互的数据同步方法和装置,可实现以少量网络流量传输完成数据同步。
为了实现上述目的,本发明采用以下技术方案:
本发明一方面提出一种可离线交互的数据同步方法,包括:
为每个用户设置一根远端指针指向最后一次获取服务器变更记录的位置;
当用户处于离线状态时,将从远端指针开始的本地位置到恢复网络的位置的变更记录标记为未同步状态,直到服务器恢复网络,用户向服务器获取远端指针到最新时间段内的状态变更记录;
从服务器中获取该记录后,用户将已经同步过的记录接上此时获取到的操作记录,然后将未同步的记录同步到服务器上,并在本地的记录上追加该段未同步的记录,最终完成数据同步的过程。
进一步地,未同步状态的记录被新增到服务器时,如果存在数据冲突,以网络状态良好的记录为准。
进一步地,对于新加入的用户,其远端指针指向服务器中的最后一条变更记录,新用户在此基础上提交自己的变更即可完成数据同步的过程。
本发明另一方面提出一种可离线交互的数据同步装置,包括:
远端指针设置模块,用于为每个用户设置一根远端指针指向最后一次获取服务器变更记录的位置;
状态变更记录获取模块,用于当用户处于离线状态时,将从远端指针开始的本地位置到恢复网络的位置的变更记录标记为未同步状态,直到服务器恢复网络,用户向服务器获取远端指针到最新时间段内的状态变更记录;
数据同步模块,用于从服务器中获取该记录后,用户将已经同步过的记录接上此时获取到的操作记录,然后将未同步的记录同步到服务器上,并在本地的记录上追加该段未同步的记录,最终完成数据同步的过程。
进一步地,未同步状态的记录被新增到服务器时,如果存在数据冲突,以网络状态良好的记录为准。
进一步地,对于新加入的用户,其远端指针指向服务器中的最后一条变更记录,新用户在此基础上提交自己的变更即可完成数据同步的过程。
与现有技术相比,本发明具有的有益效果:
本发明只需要交换少量操作记录,所以对网络情况要求极低,在网络不稳定时,仍然可流畅运行应用。基于增量的历史操作记录以少量网络流量传输完成数据同步:因为只关注在加入之后的事情,所以只需要获取当前最新的数据即可,服务器给客户端的只是占用流量很小的历史记录数据,所以可以极大的降低网络层面的消耗从而提高网络层面的性能。
具体实施方式
下面结合附图和具体的实施例对本发明做进一步的解释说明:
一个服务器对应着N个用户(客户端),客户端通过使用服务器提供的接口和服务器进行数据交互。而这些改变数据状态的接口都可以看作是一次对数据变更操作,通过记录这些数据的变更记录可以形成一张变更记录的表,如:变更记录为 数据A->变更方式1->数据B->变更方式2->数据C->变更方式3->数据D。而我们不需要记录具体的数据只需要记录这些变更记录最终在本地还原就可得到最终的实时数据。
如图1所示:用户A与用户B同时操作服务器中的数据,在第1个时间点上A操作了数据1, 在第2、3时间点上B操作了数据2和数据1,因为时间点3处于时间点1之后所以A最初的操作一定会被覆盖,这是无异议的。但是B在时间点5和时间点6进行数据更改时,自己突然断网了,此时有一个最大的问题是,在联网后如何将用户B产生的修改更新到服务器中,此时我们提出了一种可离线交互的数据同步方法,如图2所示:
用户B此时有一根远端指针指向最后一次获取服务器变更记录的位置。其外,在离线状态下产生的操作记录被记录在本地分支下,此时想要同步给服务器是不可能的,所以从远端指针开始的本地位置到恢复网络的位置的这一段变更记录被标记为未同步状态,直到服务器恢复网络,此时用户B将会向服务器获取远端指针到最新时间段内的状态变更记录。从服务器中拿到该记录后,用户B将已经同步过的记录接上此时获取到的操作记录,然后将未同步的记录此时同步到服务器上,然后在本地的记录上追加自己提交的这一段记录,最终完成数据同步的过程。
这期间以下问题的解决方式
问题一(离线修改的数据冲突如何处理):如果未同步状态的记录被新增到服务器,此时如果存在数据冲突应当以网络状态良好的记录为准,这是作为合并冲突的断网惩罚,以保证数据的最终一致性为设计核心理念。
问题二(新加入进来的用户如何处理):如果该***运行了很久则一定会产生大量的操作记录,而新加入进来的用户是不需要关心那么多的数据变更记录的,只需要记录服务器当前最新的数据即可,此时远端指针指向服务器中的最后一条变更记录,然后新用户在此基础上提交自己的变更即可完成数据同步的过程。
问题三(服务器变更记录为何不按时间线):如果按照时间线来存储,就维持不了数据的最终一致性了,比如说:用户A的存储记录是 记录A(时间点1)->记录B(时间点2)->记录C(时间点4),用户B的存储记录是 记录A->记录B->记录C,服务器的记录也是 记录A->记录B->记录C,用户A和B的远端指针都指向记录C。然后用户C产生记录D(时间点3),若是按照时间点来做操作记录,则会变成记录A(时间1) -> 记录B(时间点2) -> 记录D(时间点3)-> 记录C(时间点4),而此时如果用户A和用户B再去通过远端指针同步操作记录时,就会导致记录丢失。
问题四(远端指针存在的意义):因为是一个多用户也就是多个客户端操作的***,所以当用户较多的时候就会导致操作记录异常混乱,如果远端指针存在,只需获取指针指向的记录到最新的记录这一段,即可快速的拿到自己缺失的一段,而不需要做一系列记录校验操作。
具体示例如下:
第一步:服务器初始化服务器数据Data_A、Data_1,并初始化变更记录队列Qs,客户端A、B、C分别向服务器端发送请求,并分别初始化自己本地的远端指针ptr_s,此时Qs队列无记录, ptr_s将指向队列的开始处完成初始化,同时客户端根据ptr_s生成本地队列,因Qs无数据所以初始化队列为空,随着ptr_s传递的还有初始版本的数据Data_A以及Data_1,初始化完成后所有的客户端记录着当前的数据Data_A、Data_1。
第二步:客户端A在时间点T1操作应用后(Data_A根据操作变更为Data_B)产生操作记录A_1,记录内容为Data_A -> A_1 => Data_B,客户端A请求服务器做A_1操作,服务器将Data_A经过A_1得到数据Data_B(Data_A -> A_1 => Data_B),A_1<T1>作为第一条数据***到Qs中,然后将成功状态告知客户端A(sc -> A)。
第三步:服务器将状态变更记录通知给除A以外的客户端(qc -> B)(qc -> C),客户端B收到变更通知通过本地指针ptr_s请求服务器获取到变更记录A_1<T1>,客户端B接收到A_1<T1>后对Data_A进行推演(Data_A -> A_1 => Data_B),客户端C操作同上。
第四步:客户端D在中途加入进来,客户端D向服务器端请求,此时服务器端返回最新数据Data_B、Data_1,客户端D初始化ptr_s指针指向A_1<T1>,初始化本地数据为Data_B。
第五步:客户端D在时间点T2操作应用产生操作记录D_1(Data_B -> D_1 =>Data_E),客户端D请求服务器做出D_1操作,但是客户端D断网,导致操作D_1无法传递给服务器,记录D_1被标记为D*_1。客户端D在时间点T3操作应用又产生操作记录D_2(Data_1 ->D_2 => Data_2),客户端D请求服务器做出D_2操作,但是因为客户端D依旧断网,服务器还是无法接收到消息,记录D_2被标记为D*_2,并将这两条记录当作异常记录进行记录。
第六步:客户端C在时间点T4操作应用产生操作记录C_1(Data_B -> C_1 =>Data_C),客户端B请求服务器做出C_1操作,服务器将Data_B经过C_1得到数据Data_C(Data_B -> C_1 => Data_C),C_1<T4>作为第一条数据***到Qs中,然后将成功状态告知客户端C(sc -> C)。此时Qs中的记录为(A_1<T1> -> C_1<T4>)。
第七步:服务器将状态变更记录通知给除A以外的客户端(qc -> B)(qc -> C),客户端B收到变更通知通过本地指针ptr_s请求服务器获取到ptr_s之后到最新的这一段区间内的变更记录也就是C_1<T4>,客户端A接收到C_1<T4>后对本地数据Data_B进行推演(Data_B -> C_1 => Data_C),客户端B同上,客户端C处于离线状态不做更改(也做不了更改)。
第八步:客户端D恢复网络,此时会将D*_1<T2>、D*_2<T3>这两条记录一同推送到服务器,并告知服务器当前自己所指向的记录ptr_s,服务器发现是异常状态,依次取出异常状态记录中的一条(如D*_1<T2>)后从ptr_s开始的下一条记录进行比较直到最后一条记录。如果发现D*_1<T2>与记录产生冲突,将会把D*_1<T2>标记为*D_1<T2>表示该条是需要忽略的记录,这是必要的离线惩罚。然后将其***到Qs的末尾,此时Qs的状态为(A_1<T1> -> C_1<T4> -> *D_1<T2>),此时数据的状态为Data_C、Data_1。然后取出异常记录D*_2<T3>,从ptr_s开始的下一条记录进行比较直到最后一条记录。如果发现D*_2<T3>没有与这一个区间内的任何一条记录产生冲突,将D*_2<T3>作为一条正常记录D_2<T3>***到末尾,也就是*D_1<T2>的后边,然后数据Data_1更新(Data_1 -> D_2<T3> => Data_2),此时Qs状态为(A_1<T1> -> C_1<T4> -> *D_1<T2> -> D_2<T3>),数据变更为Data_C、Data_2。
第九步:服务器通知所有的客户端,认领从ptr_s指向的下一条记录到最新的记录区间,并将ptr_s更新到指向服务器最新的一条记录。
第十步:客户端D取到记录(C_1<T4> -> *D_1<T2> -> D_2<T3>),在本地对自己本地的数据Data_B和Data_1进行推演得到新的数据Data_C和Data_2然后将(C_1<T4> -> *D_1<T2> -> D_2<T3>)加入到自己的历史记录中,此时客户端D的历史记录为(A_1<T1> -> C_1<T4> -> *D_1<T2> -> D_2<T3>)。客户端A的历史记录为(A_1<T1> -> C_1<T4>),ptr_s指向C_1<T4>,所以客户端A拿到的记录为(*D_1<T2> -> D_2<T3>),ptr_s指向服务器端最新的一条数据。然后执行推演操作,完成后自己的记录更新为(A_1<T1> -> C_1<T4> -> *D_1<T2> -> D_2<T3>),此时A的数据状况为Data_C和Data_2。客户端B、C同客户端A。
在上述实施例的基础上,本发明另一方面提出一种可离线交互的数据同步装置,包括:
远端指针设置模块,用于为每个用户设置一根远端指针指向最后一次获取服务器变更记录的位置;
状态变更记录获取模块,用于当用户处于离线状态时,将从远端指针开始的本地位置到恢复网络的位置的变更记录标记为未同步状态,直到服务器恢复网络,用户向服务器获取远端指针到最新时间段内的状态变更记录;
数据同步模块,用于从服务器中获取该记录后,用户将已经同步过的记录接上此时获取到的操作记录,然后将未同步的记录同步到服务器上,并在本地的记录上追加该段未同步的记录,最终完成数据同步的过程。
进一步地,未同步状态的记录被新增到服务器时,如果存在数据冲突,以网络状态良好的记录为准。
进一步地,对于新加入的用户,其远端指针指向服务器中的最后一条变更记录,新用户在此基础上提交自己的变更即可完成数据同步的过程。
综上,本发明适用于操作性强,对数据实时性要求没有那么高的***或应用,如:***管理,因为该方案只需要交换少量操作记录,所以对网络情况要求极低,在网络不稳定时,仍然可流畅运行应用。基于增量的历史操作记录以少量网络流量传输完成数据同步:因为只关注在加入之后的事情,所以只需要获取当前最新的数据即可,服务器给客户端的只是占用流量很小的历史记录数据,所以可以极大的降低网络层面的消耗从而提高网络层面的性能。
以上所示仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。