美文网首页
Redis-pipeline实现简单的限流

Redis-pipeline实现简单的限流

作者: lv_shun | 来源:发表于2020-05-07 23:38 被阅读0次

今天讨论分布式应用中的限流问题,这里通过redis的pipeline实现个简单的限流。
这里先简单说一下pipeline。
redis服务器处理命令的时间是微秒级别的,所以时间消耗主要在网络传输过程中,为了解决这个问题产生了pipeline,就是批量将命令打包发送到redis服务器,然后服务器按顺序执行命令,并将结果按顺序返回到客户端。这样已降低网络交互。
但是pipeline打包的命令不是原子性的,有可能被打散加入等待队列中,至于原理就不在这里展开了。

现在要实现一个60秒内,只允许某用户执行某种行为5次的限流。需求比较简单,需要有个时间滑块的概念,只统计在60内时间范围的请求,其他的数据可以丢弃。这里使用的是zset结构,直接上代码。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class DemoTest {

    @Autowired
    RedisTemplate redisTemplate;
 @Test
    public void PipelineTest() {
        //用户id
        String userId = "zhangsan";
        //行为key
        String actionKey = "good";
        //时间范围
        Integer period = 60;
        //次数上限
        Integer maxCount = 5;

        for (int i = 0; i < 20; i++) {
            List<Object> list = redisTemplate.executePipelined(new RedisCallback<Long>() {

                @Override
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.openPipeline();
                    String key = String.format("hist:%s:%s", userId, actionKey);
                    long nowTs = System.currentTimeMillis();
                    //添加行为
                    connection.zAdd(key.getBytes(), nowTs, (nowTs + "").getBytes());
                    //清理无用的数据
                    connection.zRemRangeByScore(key.getBytes(), 0, nowTs - period * 1000);
                    //设置key有效时间 对冷数据自动清理
                    connection.expire(key.getBytes(), period + 1);
                    //获取次数
                    Long card = connection.zCard(key.getBytes());
                    return card;
                }
            });

            System.out.println(list);
            if((Long)list.get(list.size() - 1) >= maxCount) {
                System.out.println("已经超出最大点赞量");
                break;
            }
        }
    }
}

这里使用了redisTemplate作为客户端,通过zset中的key的命名来确定用户行为。通过时间戳设置value和score,便于删除和范围获取,在将对象设置有效时长,来对无行为的用户数据进行自动清理,这样就完成了简单的限流功能。也算是zset的一种应用场景吧。

参考《Redis深度历险》

相关文章

  • Redis-pipeline实现简单的限流

    今天讨论分布式应用中的限流问题,这里通过redis的pipeline实现个简单的限流。这里先简单说一下pipeli...

  • SpringBoot基于RateLimiter+AOP动态的为不

    一 限流实现: RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根...

  • 限流器的简单实现

    问题分析 场景 场景如下:我们有10w台设备,这10w台设备会不定时向服务端上报数据,如果消息的并发量比较大的话,...

  • 基于令牌桶算法的Java限流实现

    项目需要使用限流措施,查阅后主要使用令牌桶算法实现,为了更灵活的实现限流,就自己实现了一个简单的基于令牌桶算法的限...

  • 基于计数器的服务接口限流实例

    计数器限流是服务接口限流策略中最为基本和简单的方式。本实例将实现不同接口设置不同的限流方案。 首先我们需要需要定义...

  • guava 限流的实现

    使用 google guava 实现简单的限流 参考 https://ifeve.com/guava-rateli...

  • 简单的限流 java实现 RateLimiter

    1. 基于QPS的限流 即单位时间的请求数不能超过一个阈值 2.基于并发访问的限流 即并发数不能超过阈值 这个记得...

  • PHP中接口限流实现

    代码中实现单个用户限流,uid换为接口名,即可实现接口限流

  • 经典限流算法:令牌桶算法

    Guava 的限流器使用上还是很简单的,那它是如何实现的呢?Guava 采用的是令牌桶算法,其核心是要想通过限流器...

  • 限流算法实现

    并发数限流 1. 计数器并发数限流 2. 信号量(Semaphore) 其实最简单的方法就是用信号量来实现: QP...

网友评论

      本文标题:Redis-pipeline实现简单的限流

      本文链接:https://www.haomeiwen.com/subject/abfyoqtx.html