徐立
摘要:提出了多人同时编辑同一web页面会引起版本冲突,抽象出问题的模型,针对问题设计了一种普通编辑锁,借助Ajax技术,有效地解决了多人同时编辑同一web页面版本冲突问题,同时也避免的传统编辑锁长时间锁定被编辑页面的弊端。进一步提出粒度可配的编辑锁,除能有效解决普通编辑锁能解决的问题外,还可以通过配置细粒度来锁定更少的资源,使没必要被锁的资源处于可被编辑状态,提高系统被编辑的效率和缩短了其他用户的等待时间。
关键词:web;多人协作;版本冲突;编辑锁;粒度可配;细粒度
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)26-0059-02
随着大规模协作时代的到来,发动社区内成员共同编辑协作,集众人之力,发挥每个人的特长,高质量地完成某项任务是一件非常有意义的事情。基于“多人协作”的主要工具为wiki[1],比较有代表性的有维基百科[2]、TraceWiki、HdWiki等[3],这些工具允许多人编辑同一词条,每编辑一次生成一个版本。近几年来,基于web多人协作平台的迅速发展,相关研究非常多,主要研究焦点集中在一些宏观方面:比如在某方面的应用[4],组织模型[5]等。大多忽视了微观小问题的研究,比如:多人同时编辑同一页面时,发生冲突了怎么办?本文通过抽象出多人同时编辑同一web页面存在冲突问题的模型,设计出数据库表,借助ajax技术,解决这个问题。
1 普通编辑锁的设计
1.1 问题抽象
存在多人同时协作时的场景:某wiki网站,用户A在编辑词条A,用户B也在编辑词条A,此时,后提交的将覆盖前面提交的內容,造成冲突。如果词条很长,网站对词条进行了处理,将其分段,用户A编辑词条A的第一段,用户B同时编辑词条A的第二段,此时则不会造成冲突。
根据上述场景,将问题进行抽象,对于协作者来讲,不管是机构、客户端、网站用户等统统定义为用户user,对于被编辑的对象不管是文章还是页面上的某个模块,只要是可以被单独编辑的对象,统统定义为资源resource,问题就抽象为user通过对resource加锁独享的问题。
1.2 数据库设计
数据库被简化成三张表:user{userId,userName};resource{resourceId, resourceName ,content};lock{lockId,userId,resourceId(unique),startTime,state,heartBeatTime},User表和resource表在一般系统中已经存在,只需添加lock表即可。其简单的ER图如图1所示。
每一个可被编辑的资源在lock表中最多对应一条记录,这个可以利用数据库的唯一索引,将lock表中的resourceId设置为唯一索引来实现。
1.3 编辑锁工作流程设计
在配置文件中设置两个可配置项:一是超时时间timeout一是心跳频率heartbeat,通过timeout来解决资源被恶意或无意长期锁定的问题,通过heartbeat来确定ajax(web页面和服务器之间的异步通信[6],可以在页面无刷新的情况下完成数据在客户端和服务器之间的交互)向服务器推送最新编辑时间的频率。用户请求对某一资源编辑及编辑中和编辑结束,编辑锁的工作流程如图2所示。
其中“insert记录”是指往lock表中新添加一条记录,userId为申请编辑的用户id,resourceId为被编辑的资源的id,startTime和heartBeatTime均为系统当前时间,state为1,表示此锁可用。
“update记录”是指更新lock表中的此资源对应锁记录,主要是userId为此次申请锁定的用户id,startTime和heartBeatTime更新为系统当前时间,state更新为1,表示此锁可用。
判断lock表中该资源“记录有效”的依据为:1)state状态为0视为无效;2)state状态为1,比较当前时间与heartBeatTime之间的差值,如果该值大于heartbeat,视为无效;3)state状态为1,比较当前时间与heartBeatTime之间的差值,如果该值小于heartbeat,但startTime与当前时间之间的差值大于timeout,视为无效;4)state状态为1,比较当前时间与heartBeatTime之间的差值,如果该值小于heartbeat,但startTime与当前时间之间的差值小于timeout,视为有效。
2 粒度可配编辑锁的设计
如果resource的粒度被划分越大,资源越安全,但资源被锁定的概率越大,编辑效率越低,如何锁定小粒度的资源,让更多用户可编辑自己需要编辑的资源是本节要解决的问题。为了实现灵活配置是否对最小粒度资源实施锁定,在配置文件中添加配置项isMinimum和HTMLtags,当isMinimum值为1时表示开启对最小粒度资源实施锁定。HTMLtags内容为html切分标签,以分号隔开,比如“p;pre”。
2.1 实现技术及流程
技术上采用开源的html解析工具,该工具使用纯java编写,能够解析html文件。
当isMinimum=1时,页面的html内容中以
或者
修饰的段落都是可单独编辑的,也是最小粒度资源。当用户请求编辑某段(最小粒度资源)时,其流程是与1.3节流程类似,判断文章(非最小粒度资源)被锁,流程不变。文章未被锁,继续判断段落是否被锁,流程类似于文章,只是resourceId由之前的资源id编程了原资源id+小粒度编号,在此不再重复叙述。当用户请求编辑某篇文章时(非最小粒度资源)流程在图2所示的流程图中判断过记录有效为“N”时,要增加判断段落是否被锁定,如果段落没有被锁定,其后流程不变,如果段落被锁,仍然可以给文章加锁,进入编辑页后,被锁定的段落“置灰”,显示不可被编辑。endprint
3 测试结果及分析
将设计的编辑锁进行简单的实现,以判断这种编辑锁是否能达到预期效果。准备两台计算机,一台计算机当服务器:1)安装常见的多人协作工具如开源的hdwiki;2)创建lock表;3)将编辑锁的实现进行封装,以插件的形式部署到hdwiki当中;4)在条目编辑页面调用编辑锁;5)配置文件配置heartbeat=120000(两分钟),timeout=3600000(一小时),isMinimum=1(开启最小粒度资源编辑锁),HTMLtags设置为“p;pre”。一台机器上安装虚拟机,模拟两个用户同时使用系统。
设计了几个测试用例,测试用例一:用户A编辑条目“北京”,且保存条目“北京”。用例二:用户A编辑条目“北京”几乎同时,用户B请求编辑“北京”。用例三:用户A编辑条目“北京”很短时间,比如5分钟,此时,用户B请求编辑“北京”。用例四:用户A编辑条目“北京”很短时间,比如5分钟,关掉浏览器离开电脑,用户B在两分钟内请求编辑词条“北京”。用例五,用户A编辑条目“北京”很短时间,比如5分钟,关掉浏览器离开电脑,用户B在5分钟内请求编辑词条“北京”。用例六,用户A编辑条目很久,比如超过1小时。用例7,用户A编辑条目“北京”第二段,用户B请求编辑条目“北京”。用例8,用户A编辑条目“北京”第二段,用户B请求编辑条目“北京”第二段。用例9,用户A编辑条目“北京”第二段,用户B请求编辑条目“北京”第三段。测试结果如表1所示。
测试用例覆盖了编辑锁的所有情况,且对编辑锁加入之前的正常功能也进行了覆盖,从测试结果来看,编辑锁可以对资源进行有效的保护,对原系统功能不造成任何不利影响,达到了预先设计的要求。
4 结束语
本文分析了多人协作过程中,多人同时对同一资源进行操作时可能产生冲突的问题进行了抽象,设计出一种编辑锁,有效的解决了这个问题,该编辑锁还可以灵活的配置超时时间和心跳时间来解决应系统可能存在的负载压力和资源被长期锁定的问题。通过流程的改进,实现了对更小粒度资源锁定的需求,且灵活可配。
参考文献:
[1] 马红亮, 原娟娟, 杨洋. Wiki协作学习中个体编辑行为评价模型的构建与应用[J]. 电化教育研究, 2014, 35(08):44-48+56.
[2] Liccardi I, Davis Hc, White S. CAWS: A wiki system to improve workspace awareness to advance effectiveness of coauthoring activities[C]// CHI07 Extended Abstracts on Human Factors in Computing Systems. 2007: 2555-2560.
[3] Haley E R, Collins G B, Coe D J. The wonderful world of wiki benefits students and instructors[J]. IEEE Potentials, 2008, 27(2):21-26.
[4] Rahhal C, Molli P, Weiss S, et al. Multi-synchronous collaborative semantic Wikis[J]. Lecture Notes in Computer Science, 2009, 58(2):115-129.
[5] Trevor J, Rodden T, Blair G. COLA: A lightweight platform for CSCW[J]. Computer Supported Cooperative Work, 1995, 3(2):197-224.
[6] 陳莉莉, 张丽, 刘正龙. 搜索引擎中基于状态的Ajax动态网页提取研究[J]. 计算机应用与软件, 2013, 30(7):217-220.endprint