锁定服务器场(asp.net)
本文关键字:net asp 服务器 锁定 | 更新日期: 2023-09-27 18:18:25
我想知道是否有任何方法可以在部署在多个服务器上的asp.net web应用程序上执行'锁定',使用像MySQL集群这样的分布式服务器。
例如,以更新帐户余额为例。两个请求不应同时更新相同的帐户余额。例如:
成员1帐户余额为100。
- 请求A访问服务器1,为成员1的余额增加100
- 请求B访问Server 2,为成员1的余额增加50
请求B将余额更新为150,并保存。
这些都在同一时间发生,因此丢失了信息,因为最终结果应该是250。
一个锁怎么可能使请求B必须等到请求A完成,直到它检索到余额。如果是单个进程,则可以通过应用程序范围的锁来实现。但是,由于有多个独立的进程,这将不起作用,因为服务器1没有被锁定,服务器2也没有
有什么想法或最佳实践可以做到这一点吗?这就是交易的作用。
将需要原子化的操作包装在TransactionScope
中,以将其注册到显式事务中。
这并不能完全解决陈旧数据的问题,因为一旦事务完成,如果其他并发用户正在使用旧的值进行更新,您仍然会遇到问题。
解决方案是在表上使用一个字段,该字段随行变化而变化-在SQL Server 2008中,这是rowversion类型。
仅在rowversion
未更改时更新行—如果更改了,则通知用户并返回当前值,而不进行更新。
在我创建的ORM中,我实现了一个锁定机制。每种类型的实体,如Product, Customer等,都有2个额外的字段:'LockedBy (int)'和'LockedAt (datetime)'。
LockedBy包含锁定实体的用户ID, lockedAt包含锁定实体的时间戳。
因此,当用户想要开始编辑一个实体时,代码将执行以下过程:
从数据库中获取实体,'1'为ProductID
Product p = new Product(1);
将实体锁定到当前登录的用户
entity.Lock();
保存/提交实体到数据库,Save()调用LockCheck(),如果登录用户有保存实体的权限,则返回true。
entity.Save();
用户有权限保存实体,如果:
(LockedBy < 0 || LockedBy == LoggedInUser.UserID || LockedAt < DateTime.Now.AddMinutes(-30))
注意:用户可以编辑被锁定超过30分钟的实体。如果另一个用户打开了实体(在编辑屏幕中),那么每隔15分钟它会弹出并询问用户是否还在那里,如果是,它会请求将LockedAt增加到Now(像滚动锁)
此时没有其他用户可以编辑此实体!
代码/用户可以随心所欲地编辑这个实体,并确保它没有在背后被改变:)
一旦用户停止编辑,代码调用:
entity.Unlock()
然后entity.Save()
然后释放实体,让其他用户编辑它
这就是像Redis这样的发布/订阅机制可以帮助你的地方。它本质上是一种向订阅者(其他负载均衡服务器)发送消息以让它们知道事件发生的方法。ServiceStack Redis客户端已经完全支持这个