标签:判断 记录 自动 集群部署 导致 时间 内存 取数据 内存回收
如果说分布式互斥算法讲了如何协调多个进程获取权限和根据权限有序访问共享资源,即获得访问权限的进程可以访问共享资源,其他进程必须 等待拥有该权限的进程释放权限。这个权限的设置或者产生的原理就是分布式锁。
在单机多线程环境中,遇到多个线程访问同一个共享资源(在单机情况下,这种一般称作“临界资源”,分布式情况下则叫“共享资源”)的 情况。为了维护数据的一致性,需要某种机制来保证只有满足某个条件的线程才能访问 资源,不满足条件的线程只能等待,在下一轮竞争中重新满足条件时才能访问资源。
锁是实现多线程同时访问同一共享资源,保证同一时刻只有一个线程可访问共享 资源所做的一种标记。分布式锁是指分布式环境下,系统部署在多个机器中,实现多进程分布 式互斥的一种锁。为了保证多个进程能看到锁,锁被存在公共存储(比如 Redis、 Memcache、数据库等三方存储中),以实现多个进程并发访问同一个临界资源,同一时 刻只有一个进程可访问共享资源,确保数据的一致性。
实现分布式锁有3 种主流方法,即: 基于关系型数据库实现分布式锁; 基于缓存实现分布式锁; 基于 ZooKeeper 实现分布式锁。
一.基于关系型数据库
创建一张锁表,当我们要锁住某个资源时,就在该表中增加一条记录,想要释放锁的时候就删除这条记录。 数据库对共享资源做了唯一性约束,如果有多个请求被同时提交到数据库的话,数据库会保 证只有一个操作可以成功,操作成功的那个线程就获得了访问共享资源的锁,可以进行操 作。 因为数据库需要落到硬盘上,频繁读 取数据库会导致 IO 开销大,因此这种分布式锁适用于并发量低,对性能要求低的场景。
主要有两个缺点:
二.基于缓存
所谓基于缓存,也就是说把数据存放在计算机内存中,不需要写入磁盘,减少了 IO 读写。
Redis 通常可以使用 setnx(key, value) 函数来实现分布式锁。key 和 value 就是基于缓存的分布式锁的两个属性,其中 key 表示锁 id,value = currentTime + timeOut,表示当前时间 + 超时时间。也就是说,某个进程获得 key 这把锁后,如果在 value 的时间内未释放锁,系统就会主动释放锁。
setnx 函数的返回值有 0 和 1:
Redis 通过队列来维持进程访问共享资源的先后顺序。Redis 锁主要基于 setnx 函数实现分布式锁,当进程通过 setnx<key,value> 函数返回 1 时,表示已经获得锁。排在后面的进程只能等待前面的进程主动释放锁,或者等到时间超时才能获得锁。
对于基于数据库实现分布式锁的方案来说,基于缓存实现的分布式锁的优势表现在以下几个方面:
这个方案的不足是,通过超时时间来控制锁的失效时间,并不是十分靠谱,因为一个进程执行时间可能比较长,或受系统进程做内存回收等影响,导致时间超时,从而不正确地释放了锁。无法合理控制超时时间
三.基于ZooKeeper
ZooKeeper 基于树形数据存储结构实现分布式锁,来解决多个进程同时访问同一临界资源时,数据的一致性问题。ZooKeeper 的树形数据存储结构主要由 4 种节点构成:
ZooKeeper 基于临时顺序节点实现了分布锁。
为了确保分布式锁的可用性,应保证以下几点:
标签:判断 记录 自动 集群部署 导致 时间 内存 取数据 内存回收
原文地址:https://www.cnblogs.com/moonyaoo/p/12953166.html