redis分布式锁安全吗?1、为什么需要分布式锁与分布式锁对应的是【单机锁】,在写多线程时,避免同时操作一个共享变量产生数据问题,通常会使用一把锁来【互斥】,以确保共享变量的正确性,使用范围是在同一个进程中。 若有多个进程需要同时操作一个共享资源,怎么实现互斥呢?现在的业务应用通常是微服务架构,若多个进程需要修改mysql的同一行记录时,为了避免操作乱序导致数据错误,这里就要使用【分布式锁】来解决了。 这里的做法是要有一个外部系统,当两个请求来时只会给一个进程返回成功,另一个等待。这个外部系统可以用mysql、redis或zookeeper,为了追求更好的性能,我们这里通常使用redis或Zookeeper。 2、 分布式锁怎么实现要实现【分布式锁】,就必须要有互斥的能力。我们可以使用SETNX命令,SET if Not eXists,若key不存在才会设置它的值。此时只有一个请求能成功获取锁,操作完成后还要及时释放锁。如何释放?——使用DEL命令删除这个key。 但有个很大的问题:1)程序处理业务逻辑异常,没及时释放锁;2)进程挂了,没机会释放锁。那么这个客户端就会一直占用这个锁,造成【死锁】。 3、如何避免死锁在申请锁时给key设置一个过期时间。这样无论客户端是否异常,这个锁都可以在x秒后自动释放。但这样还是有问题,现在的加锁和设置过期是两条命令,没有原子执行,还是有可能发生【死锁】。 在redis2.6.12版本之后,扩展了SET命令的参数, SET lock 1 EX 10 NX,这样就可以同时加锁和设置过期时间了。 那如果存在以下问题:1)对锁过期时间评估不准,实际上不够。2)客户端在释放锁没有检查这把锁是否还归自己持有,所就会发生释放别人锁的操作! 4、锁被别人释放怎么办客户端在加锁时,设置一个只有自己直到的【唯一标识】进去。例如可以是自己的线程ID,也可以是UUID(随机且唯一),这样在释放的时候就要先判断锁是否还归自己持有。这里释放锁用的是GET+DEL两条命令,又会有原子性问题。所以我们就可以引入Lua脚本,让redsi执行。因为redis处理每一个请求都是单线程的,在执行lua脚本时,其他请求必须等,直到lua被处理完成。 5、评估锁过期时间加锁时,先设置一个过期时间,然后开启一个【守护线程】,定时去检测这个锁的失效时间,若锁快要过期了,共享资源还未完成,那么久自动对锁进行【续期】。 如果是Java技术栈,有一个库已经把这些工作封装好了:Redisson。它是一个基于Java实现的Redis SDK客户端,在使用分布式锁时,他就采用了自动续期的方案来避免锁过期,这个守护线程我们一般叫做看门狗线程。此外,这个库还封装了很多功能:1)可重入锁;2)乐观锁;3)公平锁;4)读写锁;5)redlock等。 以上分析的都是在【单redis实例下可能出现的】问题,没有涉及到redis的部署架构细节。而我们工作中通常会采用主从集群+哨兵的模式部署,那当发生【主从切换】时,这个分布式锁还安全吗?(场景:客户端1在主库上执行SET,加锁成功-->此时主库宕机,SET命令还未同步到从库上-->从库被哨兵提升为主库,这个锁在新的主库上丢失了!! 6、redlock真的安全吗首先,redlock的方案基于两个前提:1)不再需要部署从库和哨兵实例,只部署主库;2)主库要部署多个,官方推荐至少5个实例。 也就是说,要使用redlock,至少需要部署5个redis实例,而且都是主库,他们之间没有任何关系,都是一个个孤立的实例。 整体流程:
1)为什么要在多个实例上加锁?——本质上是为了保障在部分实例宕机时,剩余的实例加锁成功,整个锁服务依旧可用。 2)为什么大多数加锁成功,才算成功?——多个redis实例一起来用,其实组成了一个分布式系统。在这里总会出现异常节点,所以我们需要考虑异常节点达到多少个也依旧不会影响整个系统的【正确性】。 3)为什么步骤3加锁成功后,还要计算加锁的累计耗时?——因为操作的是多个节点,耗时肯定比单个实例更久,且因为是网络请求,可能存在延迟、丢包等。所以即使大多数加锁成功,若枷锁的累计耗时以及超过了锁的【过期时间】,那此时有些实例上的锁已经失效了,这个锁就没意义了。 4)为什么释放锁,要操作所有节点?——在某一redis节点加锁时,可能因为网络原因导致加锁失败。在释放锁时,不管有没有加锁成功,都要释放所有节点的锁。 7、redlock存在问题性能与复杂度高:需要向多个redis节点发起加锁请求,网络延迟和节点通信成本高于单节点锁,且需处理部分节点超时的重试逻辑。 时钟依赖风险:依赖各节点时钟大致同步,若某节点时钟跳变,可能导致幻读锁(已过期的锁被判定为有效) 资源占用大:需维护多节点集群,增加部署和运维成本,对中小型应用不够友好。 适用场景:分布式系统中,单节点redis锁可能因主从切换、网络分区失效,redlock通过多节点投票机制降低锁丢失风险。容忍一定性能损耗,可以接收多节点通信开销。 8、Zookeeper 是一个分布式协调服务,基于ZAB协议(原子广播协议)提供强一致性的分布式锁、配置管理、服务发现能力。其核心数据模型为树形结构,节点可存储少量数据,并支持监听机制。 核心功能:
总之,强一致性协调服务,原生支持分布式锁和监听机制,适合对一致性要求高的分布式系统,但部署维护成本高于Redis。
参考:水滴与银弹
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |

大家好,我是程序员鱼皮。最近秋招,看到很多同学问:校招已经签了三方,但收到了更好的 offer 怎么办? 真是甜蜜的烦恼啊…… 其实这是求职阶段很容易遇到的问题。因为校招从投递 => 面试 => 录用的流程长的话可能
目录自定义实现Kubernetes CSI一、CSI架构设计目标与核心组件1.1 设计目标1.2 核心组件1.3 工作原理二、自定义CSI驱动实现步骤2.1 环境准备2.2 接口实现2.3 测试与验证2.4 镜像构建三、CSI驱动部署与功能验证3.1 部