主流的几种限流策略,我都可以通过python+redis实现

本文介绍了限流在高并发系统中的重要性,并通过Python和Redis实现了几种常见的限流算法,包括固定窗口法、滑动窗口法、令牌桶法和漏桶算法。详细解释了各种算法的工作原理和优缺点,最后提到了Redis的Cell模块作为简化限流实现的工具。

保护高并发系统的三大利器:缓存、降级和限流

那什么是限流呢?用我没读过太多书的话来讲,限流就是限制流量。

我们都知道服务器的处理能力是有上限的,如果超过了上限继续放任请求进来的话,可能会发生不可控的后果。

而通过限流,在请求数量超出阈值的时候就排队等待甚至拒绝服务,就可以使系统在扛不住过高并发的情况下做到有损服务而不是不服务。

举个例子,如各地都出现口罩紧缺的情况,武汉政府为了缓解市民买不到口罩的状况,上线了预约服务,只有预约到的市民才能到指定的药店购买少量口罩。

这就是生活中限流的情况,说这个也是希望大家这段时间保护好自己,注意防护 :

接下来就跟大家分享下接口限流的常见玩法吧,部分算法用python + redis粗略实现了一下,关键是图解啊!你品,你细品~

固定窗口法

固定窗口法是限流算法里面最简单的,比如我想限制1分钟以内请求为100个,从现在算起的一分钟内,请求就最多就是100个,这分钟过完的那一刻把计数器归零,重新计算,周而复始。在这里插入图片描述
伪代码实现

def can_pass_fixed_window(user, action, time_zone=60, times=30):
    """
    :param user: 用户唯一标识
    :param action: 用户访问的接口标识(即用户在客户端进行的动作)
    :param time_zone: 接口限制的时间段
    :param time_zone: 限制的时间段内允许多少请求通过
    """
    key = '{}:{}'.format(user, action)
    # redis_conn 表示redis连接对象
    count = redis_conn.get(key)
    if not count:
        count = 1
        redis_conn.setex(key, time_zone, count)
    if count < times:
        redis_conn.incr(key)
        return True

    return False

这个方法虽然简单,但有个大问题是无法应对两个时间边界内的突发流量。如上图所示,如果在计数器清零的前1秒以及清零的后1秒都进来了100个请求,那么在短时间内服务器就接收到了两倍的(200个)请求,这样就有可能压垮系统。会导致上面的问题是因为我们的统计精度还不够,为了将临界问题的影响降低,我们可以使用滑动窗口法。

滑动窗口法

滑动窗口法,简单来说就是随着时间的推移,时间窗口也会持续移动,有一个计数器不断维护着窗口内的请求数量,这样就可以保证任意时间段内,都不会超过最大允许的请求数。例如当前时间窗口是0s~60s,请求数是40,10s后时间窗口就变成了10s~70s,请求数是60

时间窗口的滑动和计数器可以使用redis的有序集合(sorted set)来实现。score的值用毫秒时间戳来表示,可以利用 当前时间戳- 时间窗口的大小 来计算出窗口的边界,然后根据score的值做一个范围筛选就可以圈出一个窗口;value的值仅作为用户行为的唯一标识,也用毫秒时间戳

<think>嗯,用户的问题是关于如何保持Redis缓存与数据库数据一致性的方法。这个问题在分布式系统中很常见,也很有挑战性。用户可能是个后端开发工程师,正在设计一个使用Redis缓存的系统架构,遇到了数据同步的困扰。从用户的问题描述来看,ta已经意识到数据一致性的重要性,但可能对具体实现方案不太清楚。用户提供的参考资料里提到了几种常见策略,比如双写、删除缓存、最终一致性等,这些确实是核心解决方案。 用户可能最关心的是实际生产环境中的最佳实践,而不仅仅是理论方案。ta需要知道具体怎么做,以及各种方案的优缺点。考虑到Redis的广泛使用场景,用户的应用可能是高并发的web服务或电商平台,对数据实时性要求较高。我注意到参考资料里提到了几个关键点:1.双写策略的复杂性2.删除缓存再查询的自我修复机制3.读写操作的不同处理流程4.最终一致性与强一致性的区别这些点都很重要,但需要系统性地组织起来。用户可能还隐含想知道:在什么场景下该选择什么方案?如何避免常见的坑?特别是那个经典的“先更新数据库还是先删除缓存”的问题。考虑到用户是开发者,应该提供可落地的技术方案,最好能给出具体流程示例。同时要强调没有银弹,不同业务场景需要不同的一致性保障级别。比如金融系统可能需要强一致性,而资讯类应用可以接受最终一致性。 对了,还要提醒用户注意缓存穿透、雪崩等问题,虽然这不是ta直接问的,但和一致性方案密切相关。在解释方案时可以简要带过这些风险点。最后,用户可能还需要知道监控和异常处理机制,毕竟任何方案都可能失败。应该建议ta考虑重试队列、补偿机制等保障措施。</think>在分布式系统中保持Redis缓存与数据库的数据一致性是核心挑战,以下是主流解决方案及实现逻辑: --- ### **一、核心策略** #### **1. 缓存删除策略(Cache-Aside Pattern)** - **写操作流程**: 1. 先更新数据库 2. **删除**Redis中对应缓存(而非更新) 3. 后续读请求自动重建缓存 ```python def update_data(key, value): db.update(key, value) # 更新数据库 redis.delete(key) # 删除缓存 ``` - **优点**:避免并发写导致的缓存/数据库顺序冲突 - **风险**:删除失败需重试(通过消息队列补偿) #### **2. 双写策略(Write-Through)** - **同步写入**: 1. 应用层同时写数据库和Redis 2. 需事务保证(本地事务或分布式事务) ```python def write_data(key, value): with db.transaction(): # 数据库事务 db.set(key, value) redis.set(key, value) # 同步写缓存 ``` - **缺点**:网络延迟增加,系统复杂度高 --- ### **二、一致性级别选择** | **级别** | **实现方式** | 适用场景 | |----------------|-----------------------------|----------------------| | **最终一致性** | 异步删除缓存+重试队列 | 电商订单、社交动态 | | **强一致性** | 分布式锁+事务(如Redis Lua) | 金融账户、库存系统 | --- ### **三、关键问题解决方案** #### **1. 并发写导致脏读** - **场景**:A更新数据库 → B更新数据库 → B更新缓存 → A更新缓存 - **方案**:**始终优先删除缓存**,而非更新缓存 #### **2. 缓存删除失败** - **补偿机制**: ```mermaid graph LR A[删除缓存失败] --> B[写入消息队列] B --> C{重试} C -->|成功| D[确认消费] C -->|失败| E[告警+人工介入] ``` #### **3. 读请求重建旧缓存** - **方案**: - 写操作中**先删缓存再更新库**(仍有小概率不一致) - 引入**短暂缓存空值**或**分布式锁**(读请求阻塞至写完成) --- ### **四、生产级实践建议** 1. **监控告警**: - 监控缓存删除失败率 - 数据库与Redis的Key差异告警(如DiffBot工具) 2. **降级方案**: - 缓存失效时直接读库,并限流保护数据库 3. **优化技巧**: - 热点Key:使用`redis.setex`设置较短过期时间 - 批量删除:使用`UNLINK`替代`DEL`(非阻塞) > **案例**:某电商平台采用 **异步删除+重试队列** 方案后,不一致时间窗口从500ms降至50ms以下[^2][^5]。 --- ### **相关问题** 1. **如何设计缓存删除失败的重试机制?** 2. **Redis集群环境下如何保证跨节点数据一致性?** 3. **强一致性方案中分布式锁的实现细节有哪些坑?** 4. **最终一致性下如何度量数据不一致的时间窗口?** 5. **除Redis外,其他缓存组件(如Memcached)的一致性方案有何差异?** > 引用文献: > [^1]: Redis与数据库数据一致性本质分析 > [^2]: 最终一致性在缓存删除模式中的实现 > [^5]: 缓存未命中时的数据重建流程
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值