Redis10——事务、限流器

266 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

事务

Redis 不满⾜原⼦性不⽀持 roll back不满⾜持久性数据容易丢失不满足一致性:但是可以通过乐观锁watch来实现一致性

Redis事务满足隔离性可以将多个命令打包,再按顺序执⾏所有命令不会被中途打断

使⽤multi命令开启事务,使命令进入事务队列,再通用exec命令执⾏事务队列,批量发给redis。

Redis 事务原语 multiexecdiscardwatch

  • 原子性:不支持,不会回滚且继续执行
  • 隔离性:支持,事务中的命令顺序,不会被打断,先EXEC先执行,单机redis读写操作使用单进程单线程
  • 持久性:不支持,redis 数据容易丢失
  • 一致性:不支持,要求通过乐观锁watch来实现

实现基于Redis的限流器

基于zset

限流涉及的主要算法的就是滑动窗口,将起始值和末端值都各+1即可。限流器存入Redis的zset数组,当每一次请求进来的时候,value用UUID生成,而score用当前时间戳表示,用score来计算当前时间戳之内有多少的请求数量,zset数据结构的zrange()方法可以获取2个时间戳内有多少请求。(zadd key score member)

实现方式:时间戳+滑动窗口

假设,限流为每秒钟最大流量100,100/s

(1)每次请求时,score保存当前时间戳,value保存UUID

(2)用限定时间计算1s前的时间戳

(3)用zset数据结构的zrange()方法获得1s前时间戳到当前时间戳中元素的数量

(4)放行与否取决于,元素数量是否大于100

基于list

提到限流就不得不提到令牌桶算法了。令牌桶算法提及到输入速率和输出速率,当输出速率大于输入速率,那么就是超出流量限制了。也就是说我们每访问一次请求的时候,可以从Redis中获取一个令牌,如果拿到令牌了,那就说明没超出限制,而如果拿不到,则结果相反。

依靠上述的思想,我们可以结合Redis的List数据结构很轻易的做到这样的代码,只是简单实现 依靠List的leftPop来获取令牌。

令牌桶算法

1.首先配置一个定时任务,通过list的rpush方法每秒插入10个令牌

2.限流时,通过list的lpop方法从redis中获取对应的令牌,如果获取成功表明可以执行请求