日常总结:一

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq360694660/article/details/81085316

1、场景:操作同一张表,先查询 后插入数据,插入的数据id生成规则依赖前一次查询时。
  
举例:要求count出A表中当前月创建的数据 后再向A表中插入一条数据 数据ID=当前时间+count+1
    
问题:当并发请求过来时。执行插入操作会出现ID主键冲突的问题。
   
解决方式一:把获取id逻辑加上锁? 
   
分析:线程A B同时执行到获取ID逻辑块。A拿到锁之后,去获取id,比如count=123456 A释放锁 然后去执行插入操作。这时候还没完成插入操作。A线程失去时间片。B拿到锁获取id也是拿到:id=123456 所以该加锁方式 没有任何效果。还提高耗时。 

解决方式二:把获取id和插入新数据整个逻辑块加锁

分析:如果获取id和插入数据整个逻辑块是在一个事务中。并且插入数据 完成事务提交。这样insert操作才结束。这时候线程B再进行获取id才是获取正确的ID。

但如果完成insert操作,但没有完成事务提交(insert后面还有其他业务逻辑,整个service并未执行结束),其实未完成数据写入。即使把获取id和插入新数据整个逻辑块加锁,当B线程获取count的出的数据和A线程count出的值还是一样的,那么当执行插入操作时,还是会出现主键冲突的问题。

解决方式三:

2、场景:大数据量(万级、百万级)的数据订正操作。

举例:上线新功能,之前老的数据,为了兼容老数据同样有该功能,需要对老数据有一些初始化数据操作。

解决方式一(通用方案):如果应用接入了MetaQ消息队列,可以利用MetaQ。MetaQ百万级别消息,随便hold住。我们可以将数据查询出来,以消息的形式,抛出去。之后再慢慢去消费。 可能处理速度比较慢,但不会对系统造成太大压力。最好有一张临时表去记录数据处理情况,百万级别的数据,不可避免会有丢失的消息的情况,如果有再对丢失的数据进行处理。

解决方式二:利用多线程处理,可以使用主线程去查询老数据,然后将需要处理的老数据放入队列中,开多个子线程去队列中获取并进行处理,如果查询很快,处理很慢,那么队列中的数据会越来越多,占用的内存就会越多。系统压力就会越大。开的线程太多,对系统压力也会增大,所以,线程数,每次查询的量,需要找到一个合理临界值。提高处理效率的同时,保证系统正常功能。

总结:两种方式,都有优缺点,大数据量的处理,尽量都在凌晨进行处理。当然肯定也有其他的合理处理方式。


   

猜你喜欢

转载自blog.csdn.net/qq360694660/article/details/81085316