券池重构

lglovejava 2016-04-19

之前的券池分成两个部分,一个Job和一个Service。

Job会每分钟loop券首位(1-9),生成一批券码往数据库里面插,这里需要做一些过滤:老券池、新券池、内存券池和券表。

Service里面有9个内存券池。它会在外部请求发券时定位到某个券池,看它的券够不够,够的话直接返回,否则重新去数据库捞一批进来。捞进来之后把数据库的券码删掉。

数据库有一个额外的“捞取批次表”,主要用来做幂等(防止分布式环境下捞取相同的券):

1.生成批次ID

INSERTINTOTG_ReceiptDistributePoolBatchFetch..

SELECT@@IDENTITYASreceiptDistributePoolBatchFetchID

2.查找券池表可用券码,以备插入内存券池

SELECT*FROMTG_ReceiptDistributePool

WHEREHeadNumber=#headNumber#ANDStatus=0ANDDealID=0LIMIT0,#quantity#

######Transactionbegin######

3.更新这批券码的批次号(使用乐观锁)

UPDATETG_ReceiptDistributePool

SETSTATUS=1,ReceiptDistributePoolBatchFetchID=#fetchID#

WHERESTATUS=0ANDReceiptDistributePoolBatchFetchID=0ANDReceiptDistributePoolIDIN#poolIDs[]#

4.重新抓取这个批次的券码

SELECT*FROMTG_ReceiptDistributePoolWHEREReceiptDistributePoolBatchFetchID=#fetchID#

5.券码被输出至内存券池

6.异步将券码从物理券池删除

DELETEFROMTG_ReceiptDistributePoolWHEREReceiptDistributePoolIDIN#poolIDs[]#

######Transactionend######

问题

1.显式使用synchronized,性能堪忧

2.代码问题,如取券池逻辑(先检查后执行,非原子操作)

3.性能问题,取券码发现不够时,才急急忙忙的去数据库load

改进

1.使用生产者消费者模式

2.券池使用BlockingQueue

3.Service初始化时启动生产者线程,启10个线程向各自的内存券池填充数据

4.外部的发券请求相当于消费者线程,根据券首位从相应券池拿券。注意限时take的使用

相关推荐