美文网首页
Redis应用-简单限流策略

Redis应用-简单限流策略

作者: CorDen_0314 | 来源:发表于2019-08-29 09:09 被阅读0次

Redis应用-简单限流策略

限流的目的是通过对并发访问/请求进行限速或者对一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务。

在讲用redis实现之前,先简单介绍下redis中最重要的一种数据结构 ==zset==

1.ZSET(有序集合)

zset类似于 Java 的 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以给每个 value 赋予一个 ==score==,代表这个 value 的排序权重

ZSET的常见命令

  • ZADD key score1 member1 [score2 member2]
//向有序集合添加一个或者多个成员
C:\Users\ke_haodong>redis-cli -h  192.168.212.55 -p 6379 -a *****
192.168.212.55:6379> select 1
OK
192.168.212.55:6379[1]> zadd rank 100 java
(integer) 1
192.168.212.55:6379[1]> zadd rank 98 python 95 c++
(integer) 2
  • ZRANGE key start stop [WITHSCORES]
//通过索引区间返回有序集合指定区间内的成员
192.168.212.55:6379[1]> zrange rank 0 100
1) "c++"
2) "python"
3) "java"
  • ZCARD key
//获取有序集合的成员数
192.168.212.55:6379[1]> zcard rank
(integer) 3
  • ZREMRANGEBYSCORE key min max
//移除有序集合中给定的排名区间的所有成员
192.168.212.55:6379[1]> ZREMRANGEBYSCORE rank 95 96
(integer) 1
192.168.212.55:6379[1]> ZRANGE rank 0 100
1) "python"
2) "java"

其他的命令这里不一一列举了,下面进入正题,如何用zset实现限流

2.Redis实现简单限流

首先来看下需求场景:系统要限定用户的某个行为在==指定的时间==(period)里只能允许发生 N 次,如何使用 Redis 的数据结构来实现这个限流的功能?

解决方案:这个限流需求中我们把这个==指定的时间==当做一个滑动时间窗口,想想 zset 数据结构的 score 值,是不是可以通过 score 保存毫秒时间戳 来圈出这个时间窗口来。而且我们只需要保留这个时间窗口,窗口之外的数据都可以砍掉。zset中的value为了保持唯一性,也存放毫秒时间戳

image

上代码:

package com.kehd.RedisStudy;

import java.io.IOException;
import redis.clients.jedis.Jedis;

/***
 * redis实现简单限流
 * 
 * @author ke_haodong
 */
public class SimpleRateLimiter {

    private Jedis jedis;

    public SimpleRateLimiter(Jedis jedis) {
        this.jedis = jedis;
    }

    public boolean isActionAllowed(String userId, String actionKey, int period, int maxCount) throws IOException {

        // 1.用户id和操作id拼接作为key
        String key = String.format("%s:%s", userId, actionKey);
        long nowTs = System.currentTimeMillis();

        // 2.score和value都用毫秒时间戳
        jedis.zadd(key, nowTs, "" + nowTs);

        // 3.移除时间窗口之前的行为记录,剩下的都是时间窗口内的
        jedis.zremrangeByScore(key, 0, nowTs - period * 1000);

        // 4.获取时间窗口内的操作次数
        long count = jedis.zcard(key);

        // 5.每次为key设置过期时间,period时间内不操作,判定为冷用户
        jedis.expire(key, period * 5 + 1);
        jedis.close();

        return count <= maxCount;
    }

    public static void main(String[] args) throws IOException {
        SimpleRateLimiter limiter = new SimpleRateLimiter(new JedisUtils().getJedis());
        for (int i = 0; i < 20; i++) {
            System.out.println(limiter.isActionAllowed("kehd", "reply", 60, 10));
        }
    }
}

运行结果

true
true
true
true
true
true
true
true
true
true
false
false
false
false
false
false
false
false
false
false

这段代码有几个值得注意的点:

  • zset 集合中key值用userid + actionid表示某个用户的操作
  • zset 集合中只有 score 值非常重要,value值没有特别的意义,只需要保证它是唯一的就可以了
  • 每一个行为到来时,都维护一次时间窗口。将时间窗口外的记录全部清理掉,只保留窗口内的记录
  • 每一次都去维护一下key的得过期时间,过期后置为冷数据,节省内存

相关文章

  • Redis应用-简单限流策略

    Redis应用-简单限流策略 限流的目的是通过对并发访问/请求进行限速或者对一个时间窗口内的的请求进行限速来保护系...

  • Redis-pipeline实现简单的限流

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

  • 技术博客

    1. 基于Redis实现分布式应用限流

  • 基于Redis的限流系统的设计

    本文讲述基于 Redis的限流系统的设计,主要会谈及限流系统中限流策略这个功能的设计;在实现方面,算法使用的是令牌...

  • 基于Redis的限流系统的设计

    本文讲述基于Redis的限流系统的设计,主要会谈及限流系统中限流策略这个功能的设计;在实现方面,算法使用的是令牌桶...

  • 基于Redis的限流系统的设计【转】

    基于Redis的限流系统的设计,主要会谈及限流系统中限流策略这个功能的设计;在实现方面,算法使用的是令牌桶算法来,...

  • 高并发环境下的限流策略

    本文将从以下几个方面分析限流策略: 什么是限流限流算法限流算法的应用 什么是限流 在开发高并发系统时,有很多手段来...

  • 压力测试:必须了解的限流策略

    1、配置限流策略 2、应用限流策略 2.1、延时 2.2、不延时 注意:设定的burst与实际测量出来的burst...

  • Redis实现限流策略

    目的 当系统处理能力有限时,控制流量,限流还有一个应用目的是控制用户行为,避免垃圾请求。系统要限定用户的某个行为在...

  • 基于redis的简单限流的实现

    首先我们来看一个常见的、简单的限流策略。系统要限定用户的某个行为在指定的时间里只能允许发生N次,如何使用redis...

网友评论

      本文标题:Redis应用-简单限流策略

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