zoukankan      html  css  js  c++  java
  • 并发以及高并发

    1、如何对每秒上千场景下的分布式锁高并发优化

      如果对一个商品不加锁,就可能出现库存超卖的情况(库存15,2个用户各买10个,没有锁的情况可能出现-5的最终库存)。所以我们可以用:

      悲观锁、乐观锁、分布式锁、队列串行化、异步队列分散、Redis原子操作等等...

      现在限定了分布式锁,有个问题:如果一套请求-下单需要20毫秒,1秒就只能容许50个用户对商品的排队等候情况(分布式锁),不能做到每秒上千场景。

      解决方法:首先理解Java的ConcurrentHashMap的源码和底层原理,核心就是分段加锁。所以我们可以把1000个商品分成20段库存,客户端1000个请求进服务端的时候,随机分给20段库存,每个分段各自加锁执行...但是某个下单请求,加锁后发现分段库存不足。那么必须释放锁,换以一个分段库存,再测尝试加锁处理。

      这个方法主要缺点就是太复杂。

    2、Java 8 优化CAS性能

      1)、什么是CAS

      例如一个多个线程对一个变量不停累加/累减1,例如 private int data = 0; data ++; 当多线程执行就可能会发生错误,结果并不一定会准确。 最开始的解决办法是加锁 public synchronized void add() { data ++}; 但是一个简单的Java操作用synchronizes大材小用。 所以现在用了atomic原子类private  atomicInteger data = new AtomicInteger(0); data.incrementAndGet(); 该方法即使用了CAS机制;

      CAS(compare and Set):多个线程都获取data当前值,走一个CAS的原子操作,然后所有线程拿当前值比较data的值,相等,则过滤,不相等,则进入下一个循环。

      2)、Java 8的优化
      如果线程太多,可能会进入一个无线重复的循环中。所以Java 8推出了分段CAS以及自动分段迁移机制:发现并发线程过多,就会内部分Cell数组,每个数组都是一个数值的分段。 然后一部分线程执行分段1,一分部线程执行分段2...减轻了循环的次数。 如果某个Cell的value执行CAS失败,就会找其他Cell分段执行CAS操作。

    3、并发问题的AQS理解

      AQS(AbstractQueuedSynchronizer,抽象队列同步器)是Java并发包的基础类。ReentrantLock,加锁和解锁的核心组件(ReentrantLock lock = new ReentrantLock() lock.lock();加锁 lock.unlock() 解锁)。  

      AQS对象内部有个变量state(int类型)代表加锁对象,初始值0(加锁状态值=1)。

      AQS还有个关键变量,记录当前加锁的是哪个线程,初始值null。  

      AQS还有一个等待队列,专门放加锁失败的线程(CAS机制加锁机制)。

      一句话总结:就是一个并发包的基础核心组件,实现各种锁,各种同步组件的。

    4、每秒上万并发下的springcloud参数优化

      当系统用户量增多,并发访问量增大的时候,就要优化最开始的服务架构。可以从以下几步去优化:

      1)、追本溯源,治标治本:优化核心服务的性能。不要用上百行的大sql,多表关联等。(因为单表几百万行数据量的话,执行一次sql要好几秒),对数据库只执行简单的单表查询和更新,复杂的业务逻辑全部在Java代码里面执行,例如关联和计算等等;

      2)、第二步:将ribbon和hystrix的超时时间设置在1秒内比较通用与合理。如果接口反应时间超过1秒(一般在200毫秒),就得考虑到缓存、索引、NoSQL等方法优化。 因为如果超时时间设置为几秒,如果下游服务响应时间长一点的话,那线程池里的线程就全部卡死;

      3)、第三步:如果超时时间设置为1秒,但是因为网络偶然的变化反应时间为1.5秒,那不就线程都卡死了么。所以配合超时时间,会有一个合理的重试。如果进程超时,会在重试的次数内再次去请求该机器;

      4)、第四部:涉及到重试,那么必须上接口的幂等性保障机制。例如插入数据的操作,重试了2次,那不是对数据库插入了3条一样的数据了。幂等性方法:可以在数据库建立一个唯一索引,插入数据的时候唯一索引冲突就不插入(没遇到过唯一索引,主键一般是自增)、或者通过redis放一个唯一id值,每次插入数据,都判断该值存在不,不存在该值就可以插入数据库,存在该值的话就不插入数据库。

    参考:纯洁的微笑、石杉的架构笔记、java版web项目、架构师之路、springForAll社区等公众号。

  • 相关阅读:
    狄慧201771010104《面向对象程序设计(java)》第十一周学习总结
    狄慧201771010104《面向对象程序设计(java)》第十周学习总结
    狄慧201771010104《面向对象程序设计(java)》第九周学习总结
    狄慧201771010104《面向对象程序设计(java)》第八周学习总结
    狄慧201771010104《面向对象程序设计(java)》第七周学习总结
    狄慧201771010104《面向对象程序设计(java)》第六周学习总结
    狄慧201771010104《面向对象程序设计(java)》第四周学习总结
    狄慧201771010104《面向对象程序设计(java)》第三周学习总结
    如何在cisco官网上下载Cisco packet tracer模拟器
    王之泰《面向对象程序设计(java)》课程学习总结
  • 原文地址:https://www.cnblogs.com/AlmostWasteTime/p/10134991.html
Copyright © 2011-2022 走看看