高并发

高并发 之 表处理

在以前的项目中,经常遇见一些高并发因而时常会出现重复数据。从而对我们操作的业务产生了一定的影响。


现象

由于遗留的历史原因系统对高并发应对很脆弱很无力,因而常常会出现某一个表中重复插入数据。


原因

由于网络原因,客户可能连续推送了两条重复的数据,两条数据时间间隔非常小,因此导致了我们的

```
if(用户不存在)
{
    xxxxx
    存储用户到数据库
}
else
{
    重复推送,不采取任何措施
}

```

这个操作还没有执行完毕,第二条拥有相同数据的线程已经进入并通过了if的检验,导致数据库存储了两条相同的数据。后来我自己写了个100并发的多线程测试程序,发现100条相同数据中有40条被插入到了数据库里!天啦噜!!!因此确定了是多线程的并发导致了程序的判断逻辑失效。


解决思路

  • 在表中对 身份证号 添加了唯一索引,以限制重复插入数据。

    CREATE TABLE `t_lockUser` (
      `id` bigint(10) unsigned NOT NULL AUTO_INCREMENT,
      `userId` bigint(20) NOT NULL,
      `recordTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ,
      `pkTime` date NOT NULL COMMENT '联合主键用的时间',
      `status` int(1) NOT NULL DEFAULT '1' COMMENT ,
      PRIMARY KEY (`id`),
      UNIQUE KEY `pk_userId_investFirstTime_only` (`pkTime`,`userId`)
    ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC ;

    这样使用 pkTime和userId作为唯一索引,就能保证每个用户每天只能往该表中插入一条数据。

    此外需要注意一个问题那就是倘若索引过大,消耗的资源同时也会很大。

  • 考虑使用synchronized对方法添加同步锁,但是这样会导致其他正常数据的推送线程也被阻塞,影响效率。因此不采用。

    使用对数据库添加行锁,实验发现还是会出现2条重复数据
    分析: 理论上的结果应该是1条成功,149条失败。对数据库的select语句添加行锁必须作用于某条记录,但是第一次报送时,数据库中并没有这条数据,因此行锁根本没有加上,导致第二条数据成功异步使用select语句。第一次报送成功以后,数据库中有了这条数据,select语句成功的对这条记录添加了行锁,所以后边不会出现重复数据。因此此法不可用。

  • 即想提高效率不对方法添加synchronized,又想保证数据准确性,最后使用synchronized(siteId + uid) 在Controller层加锁(保证了只有重复数据被加锁,在Controller使用的原因是因为事务会在Service调用完毕才被提交,我实验过在Service同步,150并发会出现2条重复数据,因为事务还没来得及提交)

    测试结果:测试了3次150并发 不到一秒的时间全部返回,结果1条登记成功,149条返回该作者已登记。


优化点

这种加同步锁的方法在负载均衡下的多台应用服务器会失效!因为就算Spring保证了对象是单例的,但是多台服务器肯定是多个对象!因此synchronized将无效。解决方法是在数据库层对该对接公司的唯一记录加select锁,这样就能保证数据的不重复性,但是会降低该公司推送数据的效率(相当于逐条推送),但是公司与公司之间还是并行推送的。还有一个方法就是将业务逻辑写入存储过程,然后对存储过程加锁,这种方法太麻烦了,需求有变动就必须去修改存储过程,但是效率要比前者高得多。

参考:http://m.blog.csdn.net/nikobelic8/article/details/53308543

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值