美文网首页
【JAVA】高并发和幂等

【JAVA】高并发和幂等

作者: Y了个J | 来源:发表于2019-03-24 00:20 被阅读0次

redis缓存,减少数据库操作

线程池,减少创建线程的开销

请求分流,分布式集群,nginx均衡负载

动静分离,前后端分离

数据库读写分离,分库分表,集群, 索引优化

限流策略

MQ解耦(一对多消费)、异步、缓冲(削峰), 消息添加到队列中,然后再多个线程程序去消耗队列

容错,故障隔离,降级策略,不要一个系统故障影响到其他系统

热点隔离,将秒杀和抢购做成独立系统或服务进行隔离,从而保证秒杀/抢购流程出现问题不影响主流程。

分布式中的幂等处理
1.比如前端对同一表单数据的重复提交,后台应该只会产生一个结果

2.比如我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱

3.比如发送消息,也应该只发一次,同样的短信如果多次发给用户,用户会崩溃

4.比如创建业务订单,一次业务请求只能创建一个,不能出现创建多个订单

唯一索引,防止新增脏数据

拿资金账户和用户账户来说,每个用户只能有一个资金账户,怎么防止给用户创建资金账户多个,
那么给资金账户表中的用户ID加唯一索引,在新增的时候只有一个能请求成功,剩下都会抛出唯一索引重复异常。

token机制,防止页面重复提交

要求:页面的数据只能被点击提交一次
发生原因:由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交

解决办法:
    集群环境:采用token加redis
    单JVM环境:采用token加redis或token加jvm内存

处理流程:
    数据提交前要向服务的申请token,token放到redis或jvm内存,token有效时间
    提交后后台校验token,同时删除token,生成新的token返回

token特点:要申请,一次有效性,可以限流
注意:redis要用删除操作来判断token,删除成功代表token校验通过,如果用select+delete来校验token,
存在并发问题,不建议使用

悲观锁

获取数据的时候加锁获取

select * from table_xxx where id=’xxx’ for update;

注意:id字段一定是主键或者唯一索引,不然是锁表,会出事的。

悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用

乐观锁

乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高。

乐观锁的实现方式多种多样可以通过version或者其他状态条件:

1.通过版本号实现
update table_xxx set name=#name#,version=version+1 where version=#version#

2.通过条件限制
update table_xxx set avai_amount=avai_amount - #subAmount# where avai_amount - #subAmount# >= 0

要求:avai_amount-subAmount >=0
这个情景适合不用版本号,只更新是做数据安全校验,适合库存模型,扣份额和回滚份额,性能更高。

注意:乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,上面两个sql改成下面的两个更好。

update table_xxx set name=#name#,version=version+1 where id=#id# and version=#version#

update table_xxx set avai_amount=avai_amount-#subAmount# where id=#id# and 
avai_amount-#subAmount# >= 0

分布式锁
还是拿插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁,其实就是为了控制多线程并发的操作,也是分布式系统中经常用到的解决思路。

在设计系统时,是首要考虑的问题,尤其是在像第三方支付平台,银行,互联网金融公司等涉及的网上资金系统,既要高效,数据也要准确,所以不能出现多扣款,多打款等问题,这样会很难处理,并会大大降低用户体验

死锁
死锁有四个必要条件,打破一个即可去除死锁。
1,互斥条件。 互斥条件:一个资源每次只能被一个进程使用。
2,请求与保持条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
3,不剥夺条件:线程已获得的资源,在末使用完之前,不能强行剥夺。
4,循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。

相关文章

网友评论

      本文标题:【JAVA】高并发和幂等

      本文链接:https://www.haomeiwen.com/subject/ircyvqtx.html