细品服务并发限流+Redis-cell的使用

2023-10-21 01:10

本文主要是介绍细品服务并发限流+Redis-cell的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

今天热搜“海底捞的排号系统挂掉了”,也许是今天情人节,各位情侣去海底捞约会,进入排号系统的流量猛增,导致服务支撑不住,直接挂掉,在这里只是猜测(大胆猜测,小心求证)。那我们应该如何防止因为流量突然猛增而导致服务挂掉的问题呢?那就是限流了。
那我们通过redis 来设计限流策略。

服务限流

简介

  • 通过压测我们可以压出我们服务接口可以承受最大的QPS或者TPS,但是我们压测的话只是单压并不知道在生产环境所能承受的最大流量。如果说其他业务接口也在跑,那这就很难把控这个接口在生产环境可以定多大的QPS或TPS。所以预估某个接口的所能承受的QPS和TPS还是很有水平的。我能力有限今天只聊如何限流。

时间窗口限流

什么是时间窗口?
  • TCP/IP为了提高传输效率(提高吞吐量)采用并发进行传输包,由于有ACk机制,如果等并发发出去的包都回来的话,会影响整体的发送效率,所以只要等到他需要等待的数据就进行发起第二次的传输。有人就会问了,TCP包的传输是有序的,如果并发发送的包,顺序是在后面的包先回来了,那怎么搞,那就继续等待先去的包回来再进行下次操作。
    还有就是采用了并发那还得考虑机器的性能,可不能由于发送的包太多导致发送包的服务不可用了。于是就有了滑动时间窗口协议。
  • 具体TCP/IP滑动时间窗口协议详解
  • 滑动时间窗口主要解决的问题就是控制瞬时的量,通过缓存将其分为4个区段,进行滑动处理这4个区段。当这四个区段放满后就会进行等待。想了解得更有深度,可以点击上面链接进行深度学习。下图是TCP滑动窗口示意图
    在这里插入图片描述

时间滑动窗口协议的应用

  1. 现在我们的服务使用的是java语言,现在需要实现一个滑动窗口。
    2.使用ReentrantLock(可重入锁)实现,如下图 这样有个问题就是:粒度太大了,不均匀,针对1秒一下的,没法辨析。
    我们能不能把粒度拆细了,1秒拆成10个100毫秒。每一个100毫秒有一个计数器。了解TCP/IP的应该知道,TCP/IP为了增加传输速度和控制传输速度,有个叫“滑动窗口协议”。就算拆得再细,也无法解决匀速限制速度的问题。而且还有个临界点问题,比如假如,一秒限制10个请求,在第1秒钟,第2秒 之间,第1秒后半段时间10个请求,第2秒前半段10个请求,那第1秒后半段+第2秒前半段时间组成的一秒钟里就有20个请求,没有起到限速的作用。
    在这里插入图片描述

  2. java中的JUC包中的CyclicBarrier。实现一个限流。我们只允许最多执行多少个线程。如果其中一个阻塞了。那这就很尴尬了。会影像服务的正常的吞吐,但是上面的那种方式,当他阻塞了后,随着时间窗口的推进,会将上一次时间串口的请求的技术进行归零。

漏斗限流

漏斗限流是最常用的限流方法之一,顾名思义,这个算法的灵感源于漏斗(funnel)的结
构。
在这里插入图片描述

实现一个简单的漏斗算法
package 漏斗算法;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class FunnelRateLimiter {static class Funnel {//漏斗的容量int capacity;//速率float leakingRate;//剩余容量int leftQuota;long leakingTs;public Funnel(int capacity, float leakingRate) {this.capacity = capacity;this.leakingRate = leakingRate;this.leftQuota = capacity;this.leakingTs = System.currentTimeMillis();}void makeSpace() {long nowTs = System.currentTimeMillis();long deltaTs = nowTs - leakingTs;int deltaQuota = (int) (deltaTs * leakingRate);// 间隔时间太长,整数数字过大溢出if (deltaQuota < 0) {this.leftQuota = capacity;this.leakingTs = nowTs;return;}// 腾出空间太小,最小单位是 1if (deltaQuota < 1) {return;}this.leftQuota += deltaQuota;this.leakingTs = nowTs;if (this.leftQuota > this.capacity) {this.leftQuota = this.capacity;}}boolean watering(int quota) {makeSpace();if (this.leftQuota >= quota) {this.leftQuota -= quota;return true;}return false;}}private Map<String, Funnel> funnels = new ConcurrentHashMap<>();public boolean isActionAllowed(String userId, String actionKey, int capacity, float leakingRate) {String key = String.format("%s:%s", userId, actionKey);Funnel funnel = funnels.get(key);if (funnel == null) {funnel = new Funnel(capacity, leakingRate);funnels.put(key, funnel);}// 需要 1 个 quotareturn funnel.watering(1);}
}
  • 有人就会怀疑自己写的不靠谱,写在服务里面使用内存这更不靠谱,有没有可以使用的中间件,被人造好的轮子。还真有,redis-cell
Redis-cell 的使用
  • Redis 4.0 提供了一个限流 Redis 模块,它叫 redis-cell。该模块也使用了漏斗算法,并
    提供了原子的限流指令。有了这个模块,限流问题就非常简单了。
  • 该模块只有 1 条指令 cl.throttle,它的参数和返回值都略显复杂,接下来让我们来看看这
    个指令具体该如何使用
    在这里插入图片描述

上面这个指令的意思是允许「用户laoqian回复行为」的频率为每 60s 最多 30 次(漏水速
率),漏斗的初始容量为 15,也就是说一开始可以连续回复 15 个帖子,然后才开始受漏水
速率的影响。我们看到这个指令中漏水速率变成了 2 个参数,替代了之前的单个浮点数。用
两个参数相除的结果来表达漏水速率相对单个浮点数要更加直观一些。

> cl.throttle laoqian:reply 15 30 60
1) (integer) 0 # 0 表示允许,1 表示拒绝
2) (integer) 15 # 漏斗容量 capacity
3) (integer) 14 # 漏斗剩余空间 left_quota
4) (integer) -1 # 如果拒绝了,需要多长时间后再试(漏斗有空间了,单位秒)
5) (integer) 2 # 多长时间后,漏斗完全空出来(left_quota==capacity,单位秒)
  • 在执行限流指令时,如果被拒绝了,就需要丢弃或重试。cl.throttle 指令考虑的非常周
    到,连重试时间都帮你算好了,直接取返回结果数组的第四个值进行 sleep 即可,如果不想
    阻塞线程,也可以异步定时任务来重试(放入一个队列进行消费队列)。

总结

  • 两种时间限流方法 时间窗口限流和漏斗限流
  • 简单介绍了时间窗口限流在TCP中的应用,TCP为了达到并发,且安全可靠传输采用时间窗口协议进行并发可靠传输包
  • 时间窗口的限流方式不能达到顺滑,为达到顺滑限流采用漏都限流。使用java简单实现漏斗限流
  • Redis4.0 中cell的使用。完美的且简单的就可以实现限流。

参考

  • 《redis 深度历险》
  • https://juejin.im/entry/6844903695432286215
  • https://www.jianshu.com/p/41781605ed29
  • 其他限流算法(令牌桶https://www.google.com/search?q=%E4%BB%A4%E7%89%8C%E6%A1%B6&oq=%E4%BB%A4%E7%89%8C%E6%A1%B6&aqs=chrome…69i57j69i59j0l4.1915j0j7&sourceid=chrome&ie=UTF-8)

这篇关于细品服务并发限流+Redis-cell的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/250923

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti