`
悲剧了
  • 浏览: 145380 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

多人操作数据的处理策略--讨论

阅读更多
用户故事如下:

电子商务后台管理,有多个客服人员可以操作同一个数据,当有的人正在对他进行修改的时候,其他人却觉得这个数据是垃圾数据,就直接删除了

如果是你,你在项目中如何处理这一小细节。

比如:当你载入订单修改的适合,有人已经把订单删除了,你去保存,不会有任何错误,反而操作成功

可以去数据库更新一个id不存在的字段,没有任何问题,只会
update  qqinfo set name='fdfd
' where id=90;

Query OK, 0 rows affected
Rows matched: 0  Changed: 0  Warnings: 0


我们目前策略如下:

对订单管理,很多工作人员都可以载入订单

特殊处理这个操作数据库的方法,设置一个字段--是否可用

可用才执行操作,操作的适合先把这个字段设为不可用

欢迎大家提出好的想法


----------------

非常谢谢大家的回复,第六页的 不知云 给出了很好的解决策略 大家可以看看

这贴就结了吧
分享到:
评论
56 楼 mht19840918 2011-05-28  
如果条件不允许,尽量考虑乐观锁,简单一点,version标志位
55 楼 mht19840918 2011-05-28  
很失败的架构,建议设计分单系统,避免锁机制
54 楼 kangxdw 2011-05-28  
楼主的应用场景只能让我想起一个词:秒杀。

只有这个场景下,会有那么多人对同一行进行操作。
有关这方面的技术,我个人觉得不是单单讨论锁能够解决的。

而且貌似当年秒杀这个概念刚炒热的时候,就有很多相关帖子。楼主可以翻出来看看啊。
53 楼 yuehan 2011-05-27  
JavaEye上面的。。。水平越来越低。哎!
52 楼 lai555 2011-05-27  
顶顶顶顶顶顶顶顶顶顶
51 楼 不知云 2011-05-26  
aaa5131421 写道
不知云 写道
aaa5131421 写道
感觉上面有些人想的太复杂了
其实这个问题就是个并发的悲观锁的问题
你update之前肯定需要select by id的吧,这时候 加上for update 不就可以了么,让这个方法序列化执行。
此时你再update 的时候就不会出现effect 0 rowcount的情况了。因为此时只有当前线程可以修改或者删除this row,其他人想做修改或删除操作,必须要等你完事才可以继续。其他线程是阻塞状态。

这时如果for update 没有成功,也就是在for update之前就已经被被人删掉的情况,你需在for update 这句下面做一个判断,如果select 出来为null,就throw 个 exception出去,展示异常页面给客户就行了。这样就完美了。



如果你select by i 的时候 加上for update,那第二个用户请求这个id数据的时候就会没响应,一直等待,直到第一个人执行完成为止。如果这样你的结果和本来有啥区别吗?还让第二个用户出现无限等待的状况。

等待的时间只是这个业务逻辑方法执行的时间,最大也只有几十毫秒而已,而且这个冲突的情况并不常出现,只是在当两个客户都同时点的时候才会出现的情况。这种情况下对客户的体验完全没有影响。说白了,这就是hibernate的悲观锁实现方式,当然,你也可以用乐观锁去做,当用乐观锁的时候,需要注意一点,如果你的业务逻辑操作中有任何一步无法回滚,就不能用乐观锁。比如你再业务逻辑中调用的第三方系统,乐观锁只能回滚数据库,回滚不了其他东西。


你说的等待时间只有几十毫秒的时间,指的是一个事务完成业务逻辑的时间,而按照LZ的意思 是在查询出订单就必须加锁,并返回到页面上,再让客服点修改或者删除按钮这段时间,这个订单都必须锁住。这段时间肯定不是你说的几十毫秒。

我引用《heberate 悲观锁和乐观锁》这篇文章的,乐观锁第二段说明一下这段时间吧:
如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时如更改用户帐户余额),如果采用悲观锁机制,也就意味着整个操作过程中(从操作员读出数、开始修改直至提交修改结果的全过程,甚至还包括操作员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对几百上千个并发,这样的情况将导致怎样的后果。

原文地址:http://www.360doc.com/content/07/0327/10/11192_415808.shtml

所以你开始说的悲观锁肯定行不通。
用乐观锁的话,理论上倒是没问题,像你说的lz的系统有分布式的话就不能用了,而且 如果这样的事情真发生 肯定会耽误客服的时间。


我觉得,如果lz的系统不是集群,用的人也不多,可以像前面有朋友说的那样,我再改进一下,首先你的系统只需要加入一个过滤器servlet,你的系统的所有业务的jsp、.do之类的请求由这个servlet过滤。如果是你的查询单一订单的页面请求就加锁,如果是其他页面就解锁。
现在详细说说怎么加锁、解锁。这个过滤器里面就只需要 管理两个静态hashmap,其中一个以订单id作为key,员工id作为value,另一个相反。如果员工进入到打开订单页面,首先查看两个map是否当前订单被锁,如果有就直接跳到其他页面,如果没有 过滤器就把员工id和当前查询出来的订单id,分别作为key和value放入这两个map中。如果员工在其他页面,过滤器就先查询当前员工id是否锁有订单,没有就继续,有就删除两个map里这个员工和它曾经锁住的订单id。

我觉得这个方法比加乐观锁和悲观锁的方式都要强,你只需要添加一个过滤器并配置它。


如果想做得更友好一些,就在你的订单列表页面查询显示前,遍历你的map锁,看当前页面的 订单是否已经有人锁定,展示的时候分别表示。
这样做的好处是,如果十个客服要处理十张订单,而且任何人都有权利处理任何一张订单,当十个客服几乎同时打开列表页,能看到哪些已经被锁定,哪些还没有,最倒霉的那个人最多也就几次就能打开一张没有锁定的订单进行处理了。
50 楼 javabrother 2011-05-26  
加個flag 做標記,用軟刪除是否可以?
49 楼 mtnt2008 2011-05-26  
kimmking 写道
乐观锁,悲观锁


+1

用乐观锁的时候,要向避免楼主的问题,可以在编辑的时候添加一个锁定按钮
48 楼 aaa5131421 2011-05-26  
不知云 写道
aaa5131421 写道
感觉上面有些人想的太复杂了
其实这个问题就是个并发的悲观锁的问题
你update之前肯定需要select by id的吧,这时候 加上for update 不就可以了么,让这个方法序列化执行。
此时你再update 的时候就不会出现effect 0 rowcount的情况了。因为此时只有当前线程可以修改或者删除this row,其他人想做修改或删除操作,必须要等你完事才可以继续。其他线程是阻塞状态。

这时如果for update 没有成功,也就是在for update之前就已经被被人删掉的情况,你需在for update 这句下面做一个判断,如果select 出来为null,就throw 个 exception出去,展示异常页面给客户就行了。这样就完美了。



如果你select by i 的时候 加上for update,那第二个用户请求这个id数据的时候就会没响应,一直等待,直到第一个人执行完成为止。如果这样你的结果和本来有啥区别吗?还让第二个用户出现无限等待的状况。

等待的时间只是这个业务逻辑方法执行的时间,最大也只有几十毫秒而已,而且这个冲突的情况并不常出现,只是在当两个客户都同时点的时候才会出现的情况。这种情况下对客户的体验完全没有影响。说白了,这就是hibernate的悲观锁实现方式,当然,你也可以用乐观锁去做,当用乐观锁的时候,需要注意一点,如果你的业务逻辑操作中有任何一步无法回滚,就不能用乐观锁。比如你再业务逻辑中调用的第三方系统,乐观锁只能回滚数据库,回滚不了其他东西。
47 楼 wuxianjun 2011-05-26  
codermouse 写道
songlixiao 写道
1. 数据库表增加一个时间戳字段。
2. 查询显示数据时,将世界戳字段查询出,并带到表单中。
3. 表单修改提交后,时间戳字段一同提交,保存前校验此数据时间戳是否与数据库一致,不一致说明已经被别人修改,不允许执行操作。
4. 如果时间戳一致,将数据的时间戳赋予当前时间,并保存到数据库。

原则是所有人都可以查询,但是修改则只有在最后一个版本上修改的才算有效。


+1

和 hibernate 乐观锁差不错。
46 楼 starcheney 2011-05-25  
<prop key="add*">PROPAGATION_SUPPORTS,-Exception</prop>
				<prop key="modify*">PROPAGATION_SUPPORTS,-Exception</prop>
				<prop key="remove*">PROPAGATION_SUPPORTS,-Exception</prop>
45 楼 HelloJimmy 2011-05-25  
kimmking 写道
乐观锁,悲观锁


正解
44 楼 不知云 2011-05-25  
aaa5131421 写道
感觉上面有些人想的太复杂了
其实这个问题就是个并发的悲观锁的问题
你update之前肯定需要select by id的吧,这时候 加上for update 不就可以了么,让这个方法序列化执行。
此时你再update 的时候就不会出现effect 0 rowcount的情况了。因为此时只有当前线程可以修改或者删除this row,其他人想做修改或删除操作,必须要等你完事才可以继续。其他线程是阻塞状态。

这时如果for update 没有成功,也就是在for update之前就已经被被人删掉的情况,你需在for update 这句下面做一个判断,如果select 出来为null,就throw 个 exception出去,展示异常页面给客户就行了。这样就完美了。



如果你select by i 的时候 加上for update,那第二个用户请求这个id数据的时候就会没响应,一直等待,直到第一个人执行完成为止。如果这样你的结果和本来有啥区别吗?还让第二个用户出现无限等待的状况。
43 楼 不知云 2011-05-25  
spell 写道
唉,这个是糟糕的设计导致的问题,有一些东西做出来是给一个人用的,不是大家可以一起用的。包括现在的很多商城,其实都有楼主所说的这个问题。

我的解决办法是,谁要处理特定的任务,先申领这条任务,每个人只可以处理自己申领或者主管分配给自己的任务,那不就OK了吗?从业务上彻底解决这个问题。表结构方面,增加user_id,处理情况等。刚开始user_id为空,分配给谁,这个user_id就记谁的,处理的时候先判断任务的user_id是不是目前登录的这个人,不是的话,不给处理。其实这个跟工作流的整合很有关系。


如果要主管分配任务才能修改任务,那就太慢了。客户打电话来,告诉你要取消订单,你还要先给主管说,让主管给你分配这个订单的任务,那客户不是要在一边凉快着呢。
如果是自己领取的话,那这个订单在没有被操作前就永远属于你自己,别人都改不了了,如果领取任务的人太忙、或者走开了,那这个任务别人就改不了,直到她操作了或者退掉任务。
如果同一个客户连接打来两个电话,第一次要求修改,第二次要求取消,两次接电话的客服几乎不会是同一个,这样第一个客服还没操作只是领取了订单任务,而第二个客服想做操作就没法弄了。

我比较赞同在使用内存map,作为锁的依据。
42 楼 不知云 2011-05-25  
songlixiao 写道
1. 数据库表增加一个时间戳字段。
2. 查询显示数据时,将世界戳字段查询出,并带到表单中。
3. 表单修改提交后,时间戳字段一同提交,保存前校验此数据时间戳是否与数据库一致,不一致说明已经被别人修改,不允许执行操作。
4. 如果时间戳一致,将数据的时间戳赋予当前时间,并保存到数据库。

原则是所有人都可以查询,但是修改则只有在最后一个版本上修改的才算有效。


如果是多个用户同一时间内都在查询这个订单,这样会造成大家谁都提交不了,一直疯狂查询这个订单,疯狂的争锁。
41 楼 codermouse 2011-05-25  
songlixiao 写道
1. 数据库表增加一个时间戳字段。
2. 查询显示数据时,将世界戳字段查询出,并带到表单中。
3. 表单修改提交后,时间戳字段一同提交,保存前校验此数据时间戳是否与数据库一致,不一致说明已经被别人修改,不允许执行操作。
4. 如果时间戳一致,将数据的时间戳赋予当前时间,并保存到数据库。

原则是所有人都可以查询,但是修改则只有在最后一个版本上修改的才算有效。


+1
40 楼 whiletrue 2011-05-25  
我们的方案是即使有很多人都有权限处理这个单子,同时也只能有一个去处理,加个签收就行了,最简单.
39 楼 leibos 2011-05-25  
悲剧了 写道
用户故事如下:

电子商务后台管理,有多个客服人员可以操作同一个数据,当有的人正在对他进行修改的时候,其他人却觉得这个数据是垃圾数据,就直接删除了

如果是你,你在项目中如何处理这一小细节。

比如:当你载入订单修改的适合,有人已经把订单删除了,你去保存,不会有任何错误,反而操作成功

可以去数据库更新一个id不存在的字段,没有任何问题,只会
update  qqinfo set name='fdfd
' where id=90;

Query OK, 0 rows affected
Rows matched: 0  Changed: 0  Warnings: 0


我们目前策略如下:

对订单管理,很多工作人员都可以载入订单

特殊处理这个操作数据库的方法,设置一个字段--是否可用

可用才执行操作,操作的适合先把这个字段设为不可用

欢迎大家提出好的想法

搞什么鬼,你们这种业务也给删除操作?这些数据根本就不应该充许删除,这是需求和设计上的问题。
如果你用hibernate,会有两个关键字可以用来解决此类问题。timestamp和version number.是hibernate提供的,数据库并不需要有此字段。
如果没用hibernate,一样可以数据库用version number这样的机制实现。

38 楼 aaa5131421 2011-05-25  
感觉上面有些人想的太复杂了
其实这个问题就是个并发的悲观锁的问题
你update之前肯定需要select by id的吧,这时候 加上for update 不就可以了么,让这个方法序列化执行。
此时你再update 的时候就不会出现effect 0 rowcount的情况了。因为此时只有当前线程可以修改或者删除this row,其他人想做修改或删除操作,必须要等你完事才可以继续。其他线程是阻塞状态。

这时如果for update 没有成功,也就是在for update之前就已经被被人删掉的情况,你需在for update 这句下面做一个判断,如果select 出来为null,就throw 个 exception出去,展示异常页面给客户就行了。这样就完美了。
37 楼 ct198312_163.com 2011-05-25  
我之前做过一个跟LZ的需求类似的东西
首先我们的并发性肯定不高,最多也就100多人同时操作。
我们当时的要求是 有一个人在修改一个数据的时候 就锁住这个具体的url 比如 /action.update?sid=1,当修改完毕之后释放这个url,或者超过一段时间就自动释放这个url的锁
实现就是放一个全局的map,key是url,value是用户ID_开始锁的时间,就维护这个map,同一个用户先锁了一个url,如果他再点了其他的url那么就一处这个key-value,如果没点,等到其他的用户访问的时候就计算时间是否超时,如果超过就可以进入
不清楚 是否对你有帮助

相关推荐

    网络多人游戏架构与编程Multiplayer Game Programming-Architecting Networked Game.pdf

    3. **服务器架构**:多人游戏通常采用客户端-服务器架构,书中会讨论单服务器、多服务器、分布式服务器等模式,以及负载均衡、故障转移和扩展性的实现方法。 4. **游戏逻辑与状态管理**:处理玩家行为和游戏世界的...

    大型多人在线游戏设计

    通过上述讨论,我们可以看出大型多人在线游戏设计中的持久化策略是一个复杂但至关重要的领域。正确的策略不仅可以保护玩家的数据不被丢失,还能提高游戏的整体性能,为玩家创造更加流畅和丰富的游戏体验。

    多人聊天软件

    4. **语音与视频通话**:多人聊天软件往往集成语音和视频通话功能,这需要高质量的音频编码/解码技术(如Opus或AAC)和视频编码/解码技术(如H.264或VP9),以及网络适应策略来处理不同网络条件下的流畅通信。...

    大型多人在线游戏开发,大型多人在线游戏开发 pdf,C,C++

    开发者需要考虑服务器的分布式部署、负载均衡、数据同步策略(如时间切片、延迟同步等)以及如何处理玩家间的交互。 3. **客户端与服务器通信**:游戏客户端和服务器之间的通信协议是关键,通常使用TCP/IP协议栈,...

    网络多人游戏架构与编程.pdf&源码

    2. **同步机制**:介绍各种同步策略,如锁步同步、基于状态机的同步、时间戳同步等,以及它们在处理玩家操作延迟和网络抖动中的应用。 3. **服务器架构**:讨论不同类型的服务器架构,如主从服务器模型、P2P(对等...

    电信设备-多人使用的个人信息系统.zip

    此外,资料可能还讨论了故障恢复和灾难备份方案,以确保即使在系统故障或自然灾害情况下,用户的个人数据也能得到保护。这通常需要定期备份和冗余存储策略。 最后,安全性更新和维护策略不容忽视。面对不断演变的...

    如何实现多人审批同一文档.docx

    在信息技术日益成熟的今天,多人协作处理文档已成为工作中不可或缺的一部分。特别是在企事业单位的日常运作中,多人审批同一文档的需求频繁出现,为了提高工作效率和协同办公质量,掌握有效的多人审批解决方案至关...

    基于Unity3D的网络多人对战策略游戏的开发与实.doc

    本文主要讨论了使用 Unity3D 开发基于网络的多人策略放置类型游戏的实际开发过程,涵盖了游戏客户端和服务端的开发、网络连接和信息交流的原理与方法、游戏热更新和游戏打包与功能测试等方面的知识点。 一、游戏...

    网络游戏-单向网络中进行数据广播的方法.zip

    通过理解网络特性和选择合适的通信协议,配合高效的数据处理策略和优化技术,可以在保证游戏体验的同时,有效管理网络资源。对于开发者来说,不断探索和实践,才能在单向网络环境中实现最佳的数据广播效果。

    多人在线聊天系统源码 xmpp+openfire

    在设计上,需要考虑用户体验,如消息的实时性、数据同步以及离线消息的处理。 **私聊和建房分组聊:** 在多人聊天系统中,私聊是指两个用户之间的个人对话,而建房分组聊则涉及创建一个聊天室,允许多个人参与讨论...

    网络游戏-具有光纤网络功能的数据处理装置.zip

    在多人在线游戏中,大量的用户同时交互,需要快速交换大量数据,光纤网络能有效降低延迟,使得游戏过程更加流畅,提高玩家的沉浸感。 数据处理装置是网络游戏系统的核心部分,它负责接收、处理和发送游戏数据。具备...

    asp.net 长连接的聊天室(多人房间)

    ASP.NET长连接的聊天室是一种实现高实时性的在线交流平台,尤其适合于多人参与的讨论环境。这种聊天室的核心技术是Comet,一种用于创建服务器推送(Server-Sent Events)的编程模型,允许服务器主动向客户端发送数据...

    毕业设计(论文)-基于JAVA的多人聊天室设计.doc

    4.3 安全性实现:介绍加密算法和安全策略,确保用户数据的安全传输和存储。 第 5 章 系统测试与优化 5.1 测试方法:列出系统测试的主要步骤,包括功能测试、性能测试、安全性测试等。 5.2 问题发现与解决:分析...

    电信设备-基于无线通信传输技术的VR多人互动系统.zip

    同时,可能会涵盖如何处理多人互动时的数据同步和网络协调问题。 【标签】为“资料”,意味着包含的文件可能是研究报告、技术文档、教程或案例分析,提供关于该主题的深入信息。 【压缩包子文件的文件名称列表】中...

    ASP.NET做的多人聊天室,无刷新

    在这个场景中,我们讨论的是一个使用ASP.NET技术实现的多人聊天室,它利用了Ajax(Asynchronous JavaScript and XML)技术来实现页面无刷新通信,提高了用户体验。在传统的Web应用中,每次用户交互都可能导致整个...

    LINQ 数据的更新,插入、删除、批量更新

    本篇文章将详细探讨如何使用LINQ进行数据的更新、插入、删除以及批量更新操作,并特别关注在多人同时修改同一条数据时如何处理冲突,以及如何通过错误处理策略来确保更新的连续性。 首先,我们来看如何使用LINQ进行...

    搭建浏览器多人测试平台并进行nagios监控

    标题 "搭建浏览器多人测试平台并进行nagios监控" 暗示了本文将讨论如何构建一个支持多用户同时测试的浏览器环境,并结合Nagios系统进行监控,以确保服务的稳定性和可用性。Nagios是一款开源的网络监控系统,能够实时...

    数据开发基础知识点-1.docx

    本篇主要讨论了三种不同的数据提交模式:主键提交(upWhereKeyOnly)、主键加改变字段提交(upWhereChanged)以及主键加数据集其他字段提交(upWhereAll)。这些模式在Query和DSP组件的updateMode属性中进行设置,每...

Global site tag (gtag.js) - Google Analytics