redis原子操作
单命令操作
多个简单的命令整合成一条命令来处理,例如:某些值的+1、-1操作,正常的流程是获取数据、修改数据、更新redis合并成INCR/DECR 命令
Lua脚本
整个Lua 脚本作为一个整体执行,在执行的过程中不会被其他命令打断,从而保证了 Lua 脚本中操作的原子性。在编写 Lua 脚本时,你要避免把不做并发控制的操作写入脚本中需要。
分布式锁
Redis单实例分布式锁
首先通过setnx获取锁,这个命令在执行时会判断键值对是否存在,如果不存在,就设置键值对的值,如果存在,就不做任何设置。
这样加锁有俩个风险:
setnx加完锁之后,程序异常导致锁没有释放,所以我们需要加上超时时间。
多个客户端一起链接redis,A加完锁之后,B正好执行释放锁的操作,导致C又可以加锁了。所以我们需要区分客户端来源,对不同的客户端加锁赋值的时候不同,然后在释放锁的时候我们需要引入lua脚本了,通过lua脚本判断释放锁的客户端是否是加锁的客户端。
多节点分布式锁(redlock)
第一步是,客户端获取当前时间。
第二步是,客户端按顺序依次向 N 个 Redis 实例执行加锁操作。(链接超时算是加锁失败)
第三步是,一旦客户端完成了和所有 Redis 实例的加锁操作,客户端就要计算整个加锁过程的总耗时。
加锁成功的条件:
条件一:客户端从超过半数(大于等于 N/2+1)的 Redis 实例上成功获取到了锁;
条件二:客户端获取锁的总耗时没有超过锁的有效时间。
事务
redis执行事务的流程,
通过MULTI命令显式的开启事务
执行客户端具体操作,这些命令虽然被客户端发送到了服务器端,但Redis 实例只是把这些命令暂存到一个命令队列中,并不会立即执行。
通过EXEC命令提交事务,这个时候才会执行具体的操作。
Redis事务-原子性、一致性:
1、命令入队时就报错,会放弃事务执行,保证原子性;
2、命令入队时没报错,实际执行时报错,正确的会被执行,错误的不执行所以不保证原子性;
3、EXEC 命令执行时实例故障,如果开启了 AOF 日志,可以保证原子性。(我们需要使用 redis-check-aof 工具检查 AOF 日志文件,这个工具可以把未完成的事务操作从 AOF 文件中去除。)
Redis事务-隔离性:
开启事务之后,发生并发修改,我们可以通过watch命令进行监控,如果在EXEC的时候,发现数据发生了变化就放弃执行。
事务提交之后,发生并发操作,因为Redis 是用单线程执行命令,而且,EXEC 命令执行后,Redis 会保证先把命令队列中的所有命令执行完。
Redis事务-持久性
AOF和RDB。