控制一个高消耗CPU的线程数控制方案

来源:互联网 发布:tcp监听端口被堵塞 编辑:程序博客网 时间:2024/06/04 17:50

由于该后台服务逻辑处理较多,还有一些复杂的计算(牛顿迭代法),后台每次跑一个线程对CPU的消耗比较高,而生产环境是4个CPU8核心(记不太清),每个核上有2个实例部署,每次通过前台调用一个CPU占用率会达到百分之百。所以需要一种方案来进行线程数控制。

开发和测试耗时2周(中间有很多小插曲进来,也是自己技术不够导致)


方案一:线程池

通过线程池的方式来控制。

需要配置线程池(线程池参数-待学习),配置与线程池关联的对应bean

缺点是:只能控制每个服务器实例上的线程数,而不能总体控制全部实例中的线程数。

方案二:数据库计数器(悲观锁)

主键ID,计数器,交易记录号,记录创建时间,记录修改时间

通过数据库特定表的一条记录中的计数器来控制。每当有一个线程进来,计数器+1,当计数器达到MAX=2时,不让其他线程继续走后边的逻辑(占用CPU较高的复杂逻辑),考虑到计数器无限增大的情况,有一个记录修改时间,在执行的时候,当计数器>=2的时候(覆盖到全部可能性,不排除意外情况下计数器>2),判断当前时间与上次更新时间间隔T,如果T大于X小时,则重置计数器,然后继续执行计数器+1以及后续逻辑。

具体:每当有一个线程进来,对这条记录进行selectfor updatewait 1(悲观锁-待学习),独立于原有事务的新事务

    在复杂逻辑执行完毕后计数器-1

wati 1的作用是:

①考虑到并发的情况下,有一个占用了其他的都会等待,这样的话其他进来的线程都在等待这个锁,而达不到控制线程数的目的;

②后台程序,update操作比较快,wait1是指的等待1秒钟,等待其他线程处理结束后再进行for update操作(如果考虑到极端的情况N个线程,必定会有几个 回oracle错误,wati1)


计数器重置作用:

如果出现计数器超过2或者负数的情况,(后来经过商议是会出现负数的情况),无法通过计数器控制,留个后门,超过两小时后业务操作人员再点可以执行,这样不至于把程序弄死上紧急版本


关于方案二:

1.DBA建议能少用forupdate就尽量少用,容易造成死锁。

2.对于时间间隔T,通过程序控制实际上并不是特别好。

另外的方案有:A界面设置重置按钮,这样不需要通过T来控制(也是有缺点)

    B乐观锁-待学习,对于进来的线程,在数据库里边加一个计数器B,不用for update wait 1方法,直接查出来后,查出计数器B=y,然后在update的时候       加上条件计数器B=y,让线程在update的时候去判断条件,没有满足条件就不更新,就返回。


这次实践中学到的东西:

多线程测试

线程和事务是两个不同的概念

考虑程序操作中利弊权衡(业务操作和机器消耗的取舍,留后门的方法)

程序健壮性考虑(一个字段不能为空,可以设置在数据库中,也可以在程序中控制,但是总有一端要考虑,跑不掉。oracle设置为not null,程序里边select出来不用考虑为null的情况了,但是insert的时候还是要考虑--躲得了初一躲不了十五^_^)

0 0