扣费类 "脏处理" 最效率解决方案

rorom 2011-07-13 02:25:07
"脏处理" 这里我说的意思 是这样的:
在业务里扣费的时候,我查询到用户余额剩下100,然后我这里需要判断用户余额是否足够支付我需要扣的钱,例如我需要扣50;
但是,与此同时另一个业务也在进行另一个业务,需要扣60,如果两个操作并发,就有可能造成判断余额是否充足的时候都显示余额是够的,但是却会把余额扣到负数,如果业务决不允许余额低于0,这种最好用什么方案处理呢?
如果不使用存储过程,也不给表加锁,同时也不把查询和处理做成一个整块的事物,还有没有什么好的办法?
...全文
112 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
rorom 2011-07-15
  • 打赏
  • 举报
回复
抱歉,这几天不能上网,谢谢各位的回复.
现在情况有些变化了,除了存储过程不能用之外,好像只要效率高的话,都可以的.
但是还是不太清楚到底哪种方式会更效率一些

另外ticmy讲的
update account set money=money-100 where money=200 具体是什么意思呢?
把判断集成到sql语句里?这样的话就不能提前知道能不能支付了,需要支付了才知道?那sql返回和sql异常要怎么处理好些?
GuuJiang 2011-07-15
  • 打赏
  • 举报
回复
你搜索一下"乐观锁 版本标识"就知道了,就是针对你这种需求的
rorom 2011-07-15
  • 打赏
  • 举报
回复
恩,感谢GuuJiang,我决定就采用你的建议的方法,确实比较方便!
同时也感谢其他朋友的建议
coooliang 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 qybao 的回复:]
做法同上,不过不需要额外的locker,使用自身类就可以了

Java code

public void pay(double x) {
synchronized(this.getClass()){ //or XXX.class XXX是你的用户类名
double d = getBalance(); //在这里再调用一次查询 ……
[/Quote]

学习!
cheneyfeng3 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 ticmy 的回复:]

update account set money=money-100 where money=200
[/Quote]

很同意这个处理方式。
beowulf2005 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 alexandertech 的回复:]

不使用存储过程,也不给表加锁,同时也不把查询和处理做成一个整块的事物,这意味着不在数据库层面来进行互斥的判断
那可以在Java代码中来互斥

比如通过将判断与扣费的代码放在一个同步代码块中就可以实现
Java code

public static byte[] block = new byte[1];
public void pay(int x) {
……
[/Quote]

这不是好办法,当业务发展,有多服务器的时候,这样的代码全部要重写。
该用Transaction的地方就要用。
龙四 2011-07-13
  • 打赏
  • 举报
回复
update account set money=money-100 where money=200
安心逍遥 2011-07-13
  • 打赏
  • 举报
回复
学习学习啊
zn85600301 2011-07-13
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 qybao 的回复:]

做法同上,不过不需要额外的locker,使用自身类就可以了
Java code
public void pay(double x) {
synchronized(this.getClass()){ //or XXX.class XXX是你的用户类名
double d = getBalance(); //在这里再调用一次查询
……
[/Quote]
加上同步就行了 出入参数的object 就是你要操作的对象
飞跃颠峰 2011-07-13
  • 打赏
  • 举报
回复
锁自身类开销太大也很浪费,对性能影响比较大
qybao 2011-07-13
  • 打赏
  • 举报
回复
做法同上,不过不需要额外的locker,使用自身类就可以了
    public void pay(double x) {
synchronized(this.getClass()){ //or XXX.class XXX是你的用户类名
double d = getBalance(); //在这里再调用一次查询
if (d>x) { //判断余额确实大于支付金额才操作,否则可以抛出异常或终止
// 执行支付
}
}
}

飞跃颠峰 2011-07-13
  • 打赏
  • 举报
回复
不使用存储过程,也不给表加锁,同时也不把查询和处理做成一个整块的事物,这意味着不在数据库层面来进行互斥的判断
那可以在Java代码中来互斥

比如通过将判断与扣费的代码放在一个同步代码块中就可以实现

public static byte[] block = new byte[1];
public void pay(int x) {
synchronized(block){
int amout=.... //获取余额
if (amount>x) {
// 执行支付
}
}
}

飞跃颠峰 2011-07-13
  • 打赏
  • 举报
回复
不使用存储过程,也不给表加锁,同时也不把查询和处理做成一个整块的事物,这意味着不在数据库层面来进行互斥的判断
那可以在Java代码中来互斥

比如通过将判断与扣费的代码放在一个同步代码块中就可以实现
public static byte[] block = new byte[1];
public void pay(int x) {
synchronized(block){
int amout=.... //获取余额
if (amount>x) {
// 执行支付
}
}
}
GuuJiang 2011-07-13
  • 打赏
  • 举报
回复
乐观锁呗

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧