- 新建的springboot启动程序包org.junit.jupiter.api不存在:检查配置文件是否引入依赖
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
- jmeter不建议直接使用GUI:
Don't use GUI mode for load testing !, only for Test creation and Test debugging.
For load testing, use CLI Mode (was NON GUI):
jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
& increase Java Heap to meet your test requirements:
Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
Check : https://jmeter.apache.org/usermanual/best-practices.html
- synchronized同步锁(这种悲观锁的方式并不推荐,会让线程一个个排队等待,降低效率)
- synchronized注意事项:
- 不能直接加在业务层的方法上 ,在业务层加了事务控制的(@Transactional),加入事务控制会导致事务也会有线程同步,以及synchronized也会有一个线程同步,事务的范围比线程同步的范围大,synchronized确实可以保证线程一个一个走,但是可能出现,synchronized结束后,事务没有结束,锁释放了,事务却没有结束,可能出现多提交的问题。
- 解决方法:1)可以把@Transactional注释掉 2)将synchronized加在控制器调用service方法大的时候使用,此时synchronized锁的范围比@Transactional范围大。比如:
synchronized(this) {
int orderId = orderService.kill(id);
}
- 乐观锁解决超卖问题,实际上是把实际的超卖问题交给数据库来解决,利用数据库中方定义的version字段,以及数据库中的‘事务’实现在并发条件下商品的超卖问题
- redis缓存库存已减1,数据库更新以及创建订单失败,导致redis缓存与数据库不一致,在创建订单失败的情况下需要恢复redis库存
- 分布式环境jvm缓存同步问题:机器a在某时刻卖完了,设置ConcurrentHashMap为true;b访问数据库存为0,将本机ConcurrentHashMap也设置为true,此时机器a在创建订单时出错Catch Exception 并将ConcurrentHashMap与库存恢复(恢复后库存将不是0);但是机器b没有Catch Exception,机器b的ConcurrentHashMap依旧为true表示售空,无法进行下面的操作。
jvm级别的缓存在分布式集群环境中如何达到一致性的 解决办法:zookpeer分布式锁,监听
- zookeeper安装版本必须与pom.xml版本一致
- redis分布式锁,需要解决的问题:
- 加锁后执行过程中出异常,会出死锁问题,需要try catch,不遇到什么错,finally释放锁;
- 加完锁宕机了,没办法finally释放锁?给锁加时长(直接使用setAbsent(k,v,time)命令一次性执行,不要使用加锁再设置时长,万一加完锁还没设置时长宕机了,会死锁)。
- 加时长,可能也会出现超卖问题,ex:第一个请求执行时间超过加锁时长,第二个请求过来加锁,第一个请求此时执行完删除锁(此时的锁是第二个请求刚加的)。解决办法,加锁时setAbsent(k,v,time)使用给线程生成一个uuid,放到v,释放锁时取v对比是否时此线程家的锁,是才允许删除
- 问题3还会有一个问题,比如匹配完是此线加的锁,正要执行删除锁操作,服务器出现了卡顿,锁到时间失效了,请求二开始加锁,加完锁,请求一卡顿结束,开始执行删除锁操作,会将请求二家的锁删除掉,所以要保证判断和删除两个操作的原子性 。解决方法锁续命,开一个子线程判断锁存在,就延长锁的时间,所以只要主线程执行不结束不删除锁,锁永远不会失效。
上述问题,可以使用redisson实现,redisson底层封装好了大量的方法,只要调用就可以。(集群环境也有可能不安全?Red lock方案在一定程度上可以解决这个问题,可以设置redis持久化,使用appendsync always :每次有新命令追加到AOF文件时就执行一次fsync,非常慢但安全,但这么样用,不如用zookeeper,效率可能好不如zookeeper)
如果对性能你要求很高并且可以允许偶尔丢锁,可以选择redis分布式锁;如果要求不丢锁,可以用zookeeper,若使用redlock不要搞主从,持久化时间间隔设置短一些,可能会更严谨
- 从CAP的角度zookeeper主要满足CP架构 redis集群架构主要满足AP架构 C:一致性 A:可用性 P:分区容错性
- 618大促的时候,提高性能,除了加机器,还需要优化代码,比如锁(分布式锁、单机锁、进程锁等)一定是先看粒度,一定要把粒度控制的越小越好,能放到锁外的代码,不要放在锁里,非必要不放在锁中。还可以分段加锁优化机制