成都做网站开发的公司,软件wap网站,调研园区网站建设工作总结,wordpress如何设置分类目录1.分布式锁
jdk的锁#xff1a; 1、显示锁#xff1a;Lock 2、隐式锁#xff1a;synchronized
使用jdk锁保证线程的安全性要求#xff1a;要求多个线程必须运行在同一个jvm中
但现在的系统基本都是分布式部署的#xff0c;一个应用会被部署到多台服务器上#xff0c;s…1.分布式锁
jdk的锁 1、显示锁Lock 2、隐式锁synchronized
使用jdk锁保证线程的安全性要求要求多个线程必须运行在同一个jvm中
但现在的系统基本都是分布式部署的一个应用会被部署到多台服务器上synchronized只能控制当前服务器自身的线程安全并不能跨服务器控制并发安全。
所以在分布式环境下要解决线程安全问题就需要使用分布式锁
思想需要在我们分布式应用的外面使用一个第三方组件可以是数据库、Redis、Zookeeper等进行全局锁的监控由这个组件决定什么时候加锁什么时候释放锁
原理在获取锁的时候插入数据如何数据可以存储成功那么就获取获取到了锁如果数据插入不成功那么就说明获取锁失败了。在进行锁释放的时候只需要将数据删除掉。 1.redis分布式锁实现业务流程: 首先我们项目中是基于原生redis实现分布式的就会涉及到一些redis原生命令 前置操作一定是缓存无数据布隆判断之后可能有数据才会在此处添动加商品自身分布式锁 使用set nx ex命令设置一个有效期为指定时间的锁我记得当时是根据多次压测结果取的值 这样会有一个问题万一在给定时间内未完成查询操作此时我们是通过后端代码自定义守护线程方式位锁进行自动续期 上面的操作如果都没有问题表示上锁成功.回源查询数据库写入缓存整个分布式锁的实现会涉及到锁的获取、判断、删除需要保证这三个操作原子性我们借助于lu脚本实现这个一般也不需要记用的时候通过文档查阅即可
1.基础实现
基于setnx命令的特性我们就可以实现一个最简单的分布式锁了。我们通过向Redis发送 setnx 命令然后判断Redis返回的结果是否为1结果是1就表示setnx成功了那本次就获得锁了可以继续执行业务逻辑如果结果是0则表示setnx失败了那本次就没有获取到锁可以通过循环的方式一直尝试获取锁直至其他客户端释放了锁delete掉key后就可以正常执行setnx命令获取到锁。流程如下 2.lua原子性操作
针对上述Redis原始命令无法满足部分业务原子性操作的问题Redis提供了Lua脚本的支持。
释放锁时
Lua脚本是一种轻量小巧的脚本语言它支持原子性操作Redis将整个Lua脚本作为一个整体执行中间不会被其他请求插入因此Redis执行Lua脚本是一个原子操作。在上面的流程中我们把get key value、判断value是否属于当前线程、删除锁这三步写到Lua脚本中使它们变成一个整体交个Redis执行改造后流程如下 解决了释放锁时取值、判断值、删除锁等多个步骤无法保证原子操作的问题了
加锁时:
在使用set key value ex seconds nx命令加锁时并不能做到重入锁的效果也就是当一个线程获取到锁后在没有释放这把锁之前当前线程自己也无法再获得这把锁这显然会影响系统的性能。使用Lua脚本就可以解决这个问题我们可以在Lua脚本中先判断锁key是否存在如果存在则再判断持有这把锁的线程是否是当前线程如果不是则加锁失败否则当前线程再次持有这把锁并把锁的重入次数1。在释放锁时也是先判断持有锁的线程是否是当前线程如果是则将锁的重入次数-1直至重入次数减至0即可删除该锁key。 2.Aop-分布式锁(首页三级分类、详情页)
分布式锁实现、A0P在项目中的使用场景
本身咱们在不使用缓存和分布式锁的情况下也可以实现详情页或者首页三级分类信息的展示使用了缓存和分布式锁只是对核心功能的一个增强按照00P思想会直接侵入代码不易维护所以需要将这种从上到下的关系优化为从左到右的增强即AOP思想AOP是spring提供的一个面向切面编程思想其底层原理是动态代理项目中是这样做的 自定了一个注解MyCache包含redis使用的key的前缀、过期时间、分布式锁key值等信息 自定义一个切面类就是一个被Aspect注解修饰的一个普通类而己在类中定义一个通知其实就是方法名around在这个方法上需要加Around注解表示我们用的是spring5通知类型中的环绕通知通过该注解的一个属性annotation对自定义注解进行增强 鉴于环绕通知的使用方法是固定的所以在定义环绕通知的时候需要注意方法返回值必须是Object类型方法形参必须是ProceedingJoinPoint的为了能够手动调用目标方法另外还需要注意环绕通知方法必须手动抛出异常信息 这样就完成了项目中对于A0P封装和使用在需要用到缓存和分布式锁的场景我们只需要将注解添加到使用的位置即可
3 如何提高分布式锁性能
1 优化分布式锁性能的关键因素
要提升分布式锁的性能首先需要了解影响性能的关键因素。以下是一些影响分布式锁性能的关键因素 锁的粒度锁的粒度越小性能通常越高。粒度较大的锁可能会导致锁争用从而降低性能。 锁的持有时间锁的持有时间越短性能越高。长时间持有锁会限制其他节点的访问。 锁的实现方式不同的分布式锁实现方式性能差异较大。使用缓存的速度比较快。 网络延迟分布式锁通常需要跨越网络进行通信网络延迟会影响性能。 锁的竞争情况如果锁的竞争情况较少性能通常较好。高度竞争的锁会导致性能下降。
2 优化技巧和最佳实践
1. 选择合适的分布式锁实现
选择合适的分布式锁实现是性能优化的关键。不同的实现方式有不同的性能特点。例如基于
Redis的分布式锁通常性能较高因为Redis是一个高性能的内存数据库而基于ZooKeeper的锁可
能性能较低因为它需要跨越网络进行通信。因此根据需求选择合适的实现方式非常重要。
2. 减小锁的粒度
将锁的粒度尽量减小可以提高性能。例如如果系统中有多个共享资源可以为每个资源使用单独
的锁而不是一个全局锁。这样可以减小锁的竞争情况提高吞
吐量。
3. 限制锁的持有时间
尽量减小锁的持有时间可以提高性能。在获取锁后尽快完成需要锁保护的操作然后释放锁让
其他节点有机会访问共享资源。
4. 使用非阻塞锁
非阻塞锁通常性能更高因为它们不会阻塞线程或进程而是会立即返回锁的状态。常见的非阻塞
锁包括乐观锁和基于CAS比较并交换的锁。
5. 考虑锁的超时和重试机制
在获取锁时考虑设置锁的超时时间和重试机制以避免出现死锁情况。如果获取锁失败可以等
待一段时间后重试或者使用指数退避策略。
6. 考虑分布式事务
在某些场景下使用分布式事务可以代替分布式锁从而提高性能。分布式事务通常比分布式锁更
高效但需要谨慎设计以确保数据一致性。