对.Net状态保持机制和并发问题的思考
2012-10-29 21:40
190 查看
最近在琢磨并发操作控制的问题,在此小小总结一下关于状态保持机制和并发解决方案,如有问题希望大家留言指正。
并发问题分为几类:
1.一个办理页面仅允许一个人进,第二个人再点就提示已经被别人访问,难点在于如何解决用户非法退出时放锁。
2.一个人“签出”后另一个人无法办理。(这是情景1的简化版)
3.多个人同时点“提交”按钮,但是系统应该只允许第一个人成功,后面的人都应该提交失败。
4.一个人更新了表单的内容到数据库,另一个人w3wp进程的用户刷新后依旧读缓存而没读取数据库,缓存不同步。
情景1和2已经在我另一篇帖子里解决了,这里主要讨论情景3和4的解决方案.
对于这种提交操作,大体来讲可以把并发控制的执行流程分为“判锁-上锁-办事-解锁”四个阶段,“锁”是一个表,可以是哈希表,也可以是数据库表。对于提交/保存这样的情景,“办事”阶段仅仅是一个十毫秒级的简单操作,那么放在数据库里显然不妥,不仅严重增大了各方的压力,而且还存在延迟问题,不保证并发安全。
接下来分析一下可能能够应用在并发控制当中的几种状态保持机制:
1.Session是一种会话相关的状态保存方式,每当浏览器去访问w3wp进程请求页面时,都会在本地生成一个写有SessionId的Cookie,浏览器负责将SessionId加到Http请求报文当中,每新开一个浏览器进程SessionId都不同。在w3wp进程内(或是状态服务当中)每个SessionId对应一张KeyValue哈希表,也就是说一个浏览器进程是读不到另一个浏览器进程写的同名Session的,因为它和会话相关,所以显然不能用作并发控制。
2.Application是一种“进程内”哈希表,问题就出在于它是和进程相关的,在多w3wp进程的情况下进程间不能共享Application,也难怪它起了这么个名字,于是它也不能拿来控制并发。
3.Cache数据缓存,广泛应用在减少数据库访问压力上,但是目前没找到接口能把它写到进程外,它和Application一样同样存在多w3wp进程的问题,w3wp进程之间是不共享缓存的。
如果不能用数据库,那么通过上面的分析,唯一要解决的问题就是这个可以跨w3wp进程的哈希表到底放在哪才能共用。我们先来解决多w3wp进程下情景4的问题。
既然是多进程,显然每个进程都有一个id,于是我们可以在Application_Start的时候给每个进程创建一个名为进程id的文件夹,假设A和B同时通过两个进程查看一个表单数据,A提交了表单修改到数据库,数据库写入成功后,可以在B的文件夹下写一个名为Guid的文件,文件里写着表单的主键id,这是对提交过程的修改。对于读取过程,B在读取缓存之前,先去遍历自己的文件夹,如果发现有A写进去的文件,则直接清缓存读库,然后删了文件。
上面的方案通过文件的方式实现了对数据修改的“通知”来使多进程间的缓存“伪同步”,但是硬盘IO毕竟有性能损耗,而且仔细分析一下,由于网络延迟,两个人在“判锁”的时候会同时成功进入后面的逻辑,有很严重的安全隐患。
最后想到的办法就是用Memcached做分布式缓存了。
并发问题分为几类:
1.一个办理页面仅允许一个人进,第二个人再点就提示已经被别人访问,难点在于如何解决用户非法退出时放锁。
2.一个人“签出”后另一个人无法办理。(这是情景1的简化版)
3.多个人同时点“提交”按钮,但是系统应该只允许第一个人成功,后面的人都应该提交失败。
4.一个人更新了表单的内容到数据库,另一个人w3wp进程的用户刷新后依旧读缓存而没读取数据库,缓存不同步。
情景1和2已经在我另一篇帖子里解决了,这里主要讨论情景3和4的解决方案.
对于这种提交操作,大体来讲可以把并发控制的执行流程分为“判锁-上锁-办事-解锁”四个阶段,“锁”是一个表,可以是哈希表,也可以是数据库表。对于提交/保存这样的情景,“办事”阶段仅仅是一个十毫秒级的简单操作,那么放在数据库里显然不妥,不仅严重增大了各方的压力,而且还存在延迟问题,不保证并发安全。
接下来分析一下可能能够应用在并发控制当中的几种状态保持机制:
1.Session是一种会话相关的状态保存方式,每当浏览器去访问w3wp进程请求页面时,都会在本地生成一个写有SessionId的Cookie,浏览器负责将SessionId加到Http请求报文当中,每新开一个浏览器进程SessionId都不同。在w3wp进程内(或是状态服务当中)每个SessionId对应一张KeyValue哈希表,也就是说一个浏览器进程是读不到另一个浏览器进程写的同名Session的,因为它和会话相关,所以显然不能用作并发控制。
2.Application是一种“进程内”哈希表,问题就出在于它是和进程相关的,在多w3wp进程的情况下进程间不能共享Application,也难怪它起了这么个名字,于是它也不能拿来控制并发。
3.Cache数据缓存,广泛应用在减少数据库访问压力上,但是目前没找到接口能把它写到进程外,它和Application一样同样存在多w3wp进程的问题,w3wp进程之间是不共享缓存的。
如果不能用数据库,那么通过上面的分析,唯一要解决的问题就是这个可以跨w3wp进程的哈希表到底放在哪才能共用。我们先来解决多w3wp进程下情景4的问题。
既然是多进程,显然每个进程都有一个id,于是我们可以在Application_Start的时候给每个进程创建一个名为进程id的文件夹,假设A和B同时通过两个进程查看一个表单数据,A提交了表单修改到数据库,数据库写入成功后,可以在B的文件夹下写一个名为Guid的文件,文件里写着表单的主键id,这是对提交过程的修改。对于读取过程,B在读取缓存之前,先去遍历自己的文件夹,如果发现有A写进去的文件,则直接清缓存读库,然后删了文件。
上面的方案通过文件的方式实现了对数据修改的“通知”来使多进程间的缓存“伪同步”,但是硬盘IO毕竟有性能损耗,而且仔细分析一下,由于网络延迟,两个人在“判锁”的时候会同时成功进入后面的逻辑,有很严重的安全隐患。
最后想到的办法就是用Memcached做分布式缓存了。
相关文章推荐
- 对.Net状态保持机制和并发问题的思考
- 《对“XXX::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们》的问题的解决方法
- 订单系统中并发问题和锁机制的探讨
- sql server在高并发状态下同时执行查询与更新操作时的死锁问题
- 解决vue跨域请求无法携带cookie,进而无法在服务器端设置session保持数据(状态)的问题
- REPLICAT RORA_1保持 ABENDED状态,无法启动问题处理
- 【译】用Fragment解决屏幕旋转(状态发生变化)状态不能保持的问题
- JAVA 并发机制--生产者消费者问题
- UITableViewCell的重绘机制导致的列状态问题
- 【译】用Fragment解决屏幕旋转(状态发生变化)状态不能保持的问题
- (4.3.1.18)Fragment重叠问题引发的思考:不保留活动下,关于Fragment 状态的保存和恢复的坑
- 解决app 监听应用退出 需要数据还原问题(例如账户登陆状态的保持)
- Mysql事务,并发问题,锁机制
- 如何让tableviewcell在拖动过后保持选中状态,避免重用机制的影响
- mysql事物 并发问题,锁机制
- PHP保持SESSION问题以及由SESSION性能引发的一些思考
- atitit. access token是什么??微信平台公众号开发access_token and Web session保持状态机制
- 查询和更新的时候带上订单状态,可以解决同一人和不同人并发产生的问题。
- 用Fragment解决屏幕旋转(状态发生变化)状态不能保持的问题
- 非托管C++调用 Webservice,如何解决状态保持的问题