如何设计一个web的订票后台服务

jkluooop 发布于 2015/10/15 13:19
阅读 544
收藏 0

 hi, all

      我在设计一个web订票程序的后台服务。初始的思路如下:
      1. 后台发布一个活动,只有10张票,相当于库存。【新建一个Tickets对象放入到缓存。】
      2. 多个web打开活动网页,选择购n张票,提交请求.
          因为同时有多个请求,java的web后台也是以线程池的方式执行请求.
          所以我给OrderService.sell()方法加synchronized,
          sell()方法里判断Tickets.total是否为0来生成订单Order,
          Order再放入缓存,设置过期时间time.
      3. 因为必须在time时间内支付,否则Order会过期掉,以空出票来提供给其他web申请。
         我用的是ehcache缓存,弄一个缓存过期 notifyElementExpired的监听器,在order没有支付的情况下又过期了,可以重新将ticket放入到Tickets里。
      4. 如果支付成功,在第三方支付的回掉方法里再将订单持久化到db.

      补充:
          之前有想过不使用缓存,直接都放数据库,只不过给订单加一个过期时间。然后后台有个定时任务一直在那里执行,清理过期的订单,并释放库存。
     //////////////////
     请问上述思路有无问题,或者这种业务场景有无一个成熟的解决办法。
     系统是jfinal写的web后台,客户端是html5,支付是第三方支付【支付宝,微信】

加载中
0
JFinal
JFinal

    如果并发要求不是很高,尽可能减少数据库方面的设计元素。涉及数据表尽可能的少,例如只涉及到 ticket、order 两张表,订票下单后 ticket 的库存字段减少,减少的量被 order 占有,order 有一个支付过期时间,使用一个线程订期回收支付过期的库存。

    此外,还建议尽量减少处理动作,业务层代码在事务中对数据库进行极少动作即可,主流程大致是:

1:启用事务,确保事务级别满足"Repeatable Read",即JDBC的事务级别值为4

2:对 ticket 库存进行判断,若库存满足则进行库存减操作

3:生成 order 记录,后续的支付成功后回调方法让 order.isPaid 字段置为 1

4:提交事务

   库存不够以及其它情况在此不在赘述。在并发不是问题的场景,建议充分利用数据库的事务特性,而非在代码层面引入一些概念来解决问题。

    最后,楼主的代码中,即便要在代码层面来模拟事务,以免有其它线程在不知不觉中操作相关数据破坏事务,要注意 OrderService 是单例的,这样在单例上调用synchronized  sell() 方法才会是多线程同步的,否则 sell() 方法需要定义成 static synchronized 才能保证非单例情况下的同步。

    

0
0x0001
0x0001
用synchronized来控制这些东西是不明智的,如果有两台web服务器的时候就有问题了, 用缓存来控制也是一样,如果缓存崩溃或重启,做这种事务方面的东西,都推给数据库吧,毕竟它才是专业干这个的
jkluooop
jkluooop
谢谢,刚看了文档,这种用数据库的乐观锁最好。队列次之,synchronized最次。
0
Solid
Solid

1、底层使用数据库,这样可以保证事务的一致性。

2、引入BlockingQueue,长度与订票人和票数有关,后来的没票了不用再排队了,直接redirect到其他页面,而且把并发访问变成串行了,降低数据库读写负载。

jkluooop
jkluooop
谢谢。这也是个思路。
返回顶部
顶部