每日八股Redis篇六应用下
【每日八股】Redis篇(六):应用(下)
Redis 如何确保集群模式下分布式锁的可靠性?
通过分布式锁算法 Redlock(红锁)来确保集群模式下分布式锁的可靠性。
Redlock 的基本思想是,基于 多个 Redis 节点 构建分布式锁。即使有某些节点发生了故障,由于锁变量依然存在,客户端仍然可以完成加锁操作。官方推荐至少部署 5 个(奇数个)Redis 节点,并且都是主节点,它们之间没有任何关系,一个个都是孤立的节点。
基本思路 :让客户端向多个独立的 Redis 节点依次申请加锁,如果客户端能够和 半数以上的节点成功地完成加锁操作 ,那么就认为,客户端成功地获得分布式锁,否则加锁失败。即使有某个 redis 节点发生故障,锁的数据在其它节点上也有保存,客户端依然可以正常地进行锁操作,锁的数据不会丢失。
Redlock 加锁的过程 :
- 第一步:客户端获取当前时间
t1
。 - 第二步:客户端按顺序依次向 N 个 Redis 节点执行加锁操作:加锁操作使用 SET NX,EX/PX 选项,并带上客户端的唯一标识。如果某个 Redis 节点发生故障了,为了保证在这种情况下 Redlock 算法能够继续运行,需要给「加锁操作」设置一个超时时间,加锁操作的超时时间需要远远地小于锁的过期时间。
- 第三步是,一旦客户端从超过半数(大于等于 N/2+1)的 Redis 节点上成功获取到了锁,就再次获取当前时间
t2
,然后计算计算整个加锁过程的总耗时t2-t1
。如果t2-t1
< 锁的过期时间,此时,认为客户端加锁成功,否则认为加锁失败。
加锁成功的两个条件 :半数以上 Redis 节点成功获取了锁,并且总耗时没有超过锁的有效时间。
Redis 管道有什么作用?
管道技术是客户端提供的一种批处理技术, 用于一次处理多个 Redis 命令,从而提高整个交互的性能 。使用管道技术可以解决多个命令执行时的网络等待,它是把多个命令整合到一起发送给服务器端处理之后统一返回给客户端,这样就免去了每条命令执行后都要等待的情况,从而有效地提高了程序的执行效率。
但使用管道技术也要注意避免发送的命令过大,或管道内的数据太多而导致的网络阻塞。 管道技术本质上是客户端提供的功能,而非 Redis 服务器端的功能 。
Redis 如何处理大 key?
大 Key 的定义 :String 类型的值大于 10 KB;Hash、List、Set、ZSet 类型的元素个数超过 5000 个;
影响 :
- 客户端超时阻塞 :由于 Redis 执行命令是单线程处理,然后在操作大 key 时会比较耗时。客户端认为很久没有响应。
- 引发网络阻塞 :每次获取大 key 产生的网络流量较大。
- 阻塞工作线程 :如果使用 del 删除大 key 时,会阻塞工作线程,这样就没办法处理后续的命令。
- 内存分布不均 :集群模型在 slot 分片均匀情况下,会出现数据和查询倾斜情况,部分有大 key 的 Redis 节点占用内存多,QPS 也会比较大。
处理方式 :
- 当 vaule 是 string 时,比较难拆分,可以使用序列化、压缩算法将 key 的大小控制在合理范围内,但是序列化和反序列化都会带来更多时间上的消耗。
- 当 value 是string,压缩之后仍然是大 key,则需要进行拆分,一个大 key 分为不同的部分,记录每个部分的 key,使用 multiget 等操作实现事务读取。
- 分拆成几个 key-value,存储在一个 hash 中,每个 field 代表一个具体的属性,使用 hget、hmget 来获取部分的 value,使用 hset,hmset 来更新部分属性
- 当 value 是 list/set 等集合类型时,根据预估的数据规模来进行分片,不同的元素计算后分到不同的片。
Redis 支持事务回滚吗?
不支持,Redis 提供的 DISCARD 命令只能用来主动放弃事务执行,把暂存的命令队列清空,起不到回滚的效果。因为 Redis 事务的执行时, 错误通常都是编程错误造成的,这种错误通常只会出现在开发环境中,而很少会在实际的生产环境中出现 ,所以官方认为没有必要为 Redis 开发事务回滚功能。