Redis是如何应对并发访问

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

在我们并发访问Redis时为了保证并发访问的正确性Redis提供了两种方法分别是加锁和原子操作。

加锁是一种常用的方法在读取数据前客户端需要先获得锁否则就无法进行操作。当一个客户端获得锁后就会一直持有这把锁直到客户端完成数据更新才释放这把锁。这种方式存在两个问题分别是加锁操作多会降低系统的并发访问性能和Redis客户端要加锁时需要用到分布式锁分布式锁实现复杂需要额外的存储系统来提供加锁操作。

原子操作是指执行过程保持原子性操作而原子操作执行时并不需要加锁实现了无锁操作既能保证并发控制还能减少对系统并发性能的影响。

加锁操作比较简单我们也常用重点看一下原子操作。

Redis的两种原子操作方法

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

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

Redis是单线程来串行处理客户端的请求操作命令的所以当Redis执行某个命令操作时其他命令是无法执行的这相当于命令操作是互斥执行的。Redis的快照生成、AOF重新这些操作可以使用后台线程或者子线程执行也就是和主线程的操作并行执行。不过这些操作只是读取数据不会修改数据所以我们并不需要对它们做并发控制。

实际应用中数据修改时可能包含多个操作至少包括读数据、数据增减、写会数据三个操作这就涉及三个操作所以Redis提供了INCR/DECR 命令把这三个操作转变为一个原子操作了。INCR/DECR 命令可以对数据进行增值 / 减值操作而且它们本身就是单个命令操作Redis 在执行它们时本身就具有互斥性。

如果执行的操作不是简单的增减数据而是复杂的判断逻辑或者其他操作Redis的单命令操作已经无法保证多个操作的互斥操作执行这个时候我们就需要使用Lua脚本。Redis会把整个Lua脚本作为一个整体执行在执行的过程中不会被其他命令打断从而保证了 Lua 脚本中操作的原子性。

如果把多个操作都放在Lua脚本中原子执行会导致Redis执行脚本的时间增加会降低Redis的并发性能所以在写Lua脚本的时候尽量避免把不需要做并发控制的操作写入脚本中。

学习来源极客时间 《Redis核心技术与实战》 学习笔记 Day19

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: redis