1. 13、Redis如何应对并发访问

解决并发访问办法: 加锁和原子操作,加锁会降低系统的并发性能。

1.1. Redis的两种原子操作方法

为了实现并发控制要求的临界区代码互斥执行,Redis的原子操作采用了两种方法

  • 把多个操作在Redis中实现成一个操作,也就是单命令操作
  • 把多个操作写到一个Lua脚本中,以原子方式执行单个Lua脚本

1.2. 如何使用Redis实现分布式锁

实现分布式锁的两个要求

  • 分布式锁的加锁和释放锁的过程,设计多个操作、所以在实现分布式锁时,我们需要保障这些锁操作的原子性。
  • 共享存储系统保存了锁变量,如果共享存储系统发生故障或宕机,那么客户端也就无法进行锁操作了,在实现分布式锁时,我们需要保障共享存储系统的可靠性,进而保障锁的可靠性。

1.3. 基于单个redis实现分布式锁

//加锁
SETNX lock_key 1
//业务逻辑
DO THINGS
//释放锁
DEL lock_key
  • 给锁设置过期时间
  • 区分来自不同的锁操作

1.4. 基于多个redis节点实现高可靠的分布式锁

  • 客户端获取当前时候
  • 客户端按顺序依次向N个Redis实例执行加锁操作
  • 一旦客户端完成了和所有Redis实例的加锁操作,客户端就要计算整个加锁过程的总耗时。

1.5. 小结

分布式锁是由共享存储系统维护的变量,多个客户端可以向共享存储系统发送命令进行加锁或释放锁操作。Redis 作为一个共享存储系统,可以用来实现分布式锁。

在基于单个 Redis 实例实现分布式锁时,对于加锁操作,我们需要满足三个条件。

  • 加锁包括了读取锁变量、检查锁变量值和设置锁变量值三个操作,但需要以原子操作的方式完成,所以,我们使用 SET 命令带上 NX 选项来实现加锁;
  • 锁变量需要设置过期时间,以免客户端拿到锁后发生异常,导致锁一直无法释放,所以,我们在 SET 命令执行时加上 EX/PX 选项,设置其过期时间;
  • 锁变量的值需要能区分来自不同客户端的加锁操作,以免在释放锁时,出现误释放操作,所以,我们使用 SET 命令设置锁变量值时,每个客户端设置的值是一个唯一值,用于标识客户端。

和加锁类似,释放锁也包含了读取锁变量值、判断锁变量值和删除锁变量三个操作,不过,我们无法使用单个命令来实现,所以,我们可以采用 Lua 脚本执行释放锁操作,通过 Redis 原子性地执行 Lua 脚本,来保证释放锁操作的原子性。

不过,基于单个 Redis 实例实现分布式锁时,会面临实例异常或崩溃的情况,这会导致实例无法提供锁操作,正因为此,Redis 也提供了 Redlock 算法,用来实现基于多个实例的分布式锁。这样一来,锁变量由多个实例维护,即使有实例发生了故障,锁变量仍然是存在的,客户端还是可以完成锁操作。Redlock 算法是实现高可靠分布式锁的一种有效解决方案,你可以在实际应用中把它用起来。 、

© gaohueric all right reserved,powered by Gitbook文件修订时间: 2021-12-08 23:22:22

results matching ""

    No results matching ""