Redis是如何应对并发访问

在我们并发访问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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

故里学Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值