第十节 SpringBoot Starter 实战之 redis 滑动窗口

使用 redis 实现滑动窗口,我们会基于这个场景,建立一个 Starter,在这之前,我们需要先。理解这个场景。

关键字:滑动窗口、流式计算、lua脚本、redis、zset、starter

概要:本文封装 redis 的API,实现简易滑动窗口,分别从业务背景、窗口理解、redis 的 zset 结构,lua 脚本,注意事项,不足等进行讲解

一、业务背景

规则预警,在特定时间触发规则达到 n 次后发出告警信息,例如:5 分钟之内失败 2 次,当满足条件后会发一条通知告警;数值可以根据实际情况动态配置。

下图是动态展示滑动窗口的示意图,按照黄色线固定窗口进行移动,窗口内会出现各种数值点,对窗口数字进行统计:

借助 redis 的 zset 有序集合能力,其中 score 字段要求有序,因此使用时间戳做 score,这样既保证顺序也能根据时间窗口计算窗口内的个数,通过计算时间窗口内的个数再与业务做判断;另外为了保障原子能力,使用lua脚本

二、redis版功能实现

通过 Lua 脚本实现 CAS(check-and-set)命令。

关于窗口在业务上的诉求,我分了三种场景,分别如下所示:

2.1 场景一、统计时间窗口内是否达到预定阈值,返回true和false, 并且达到阈值后清除

描述:1. 添加计数,2.将时间窗口外的数据移除;3.统计当前窗口的个数;4.判断是否超过阈值,5.超过清理并返回,否则返回false

redis.pcall('zadd', KEYS[1], ARGV[1], ARGV[1]);
redis.pcall('zremrangebyscore', KEYS[1], 0, ARGV[2]);
redis.pcall("expire", KEYS[1], ARGV[3]);
if tonumber(redis.pcall('zcard',KEYS[1])) >= tonumber(ARGV[4]) redis.pcall('zremrangebyscore', KEYS[1], 0, ARGV[1]);then return true end;
return false;

注意:不要使用下面这种方式。 集群方式下,不支持local变量,另外尽量少用变量,减少lua脚本占用过多内存

local key           = KEYS[1]; 
local current_time  = ARGV[1]; 
local pre_time      = ARGV[2]; 
local expire_second = ARGV[3]; 
local threshold     = ARGV[4]; 
redis.pcall("zadd", key, current_time, current_time);
redis.pcall("zremrangebyscore", key, 0, pre_time);;
local count = redis.pcall("zcard",key);
redis.pcall("expire", key, expire_second);
if tonumber(count) >= tonumber(threshold) then redis.pcall("zremrangebyscore", key, 0, current_time);return true end;
return false;

2.2 场景二、统计时间窗口内是否达到预定阈值,返回true和false, 满足true的时候不做清理

redis.pcall('zadd', KEYS[1], ARGV[1], ARGV[1]);
redis.pcall('zremrangebyscore', KEYS[1], 0, ARGV[2]);
redis.pcall("expire", KEYS[1], ARGV[3]);
if tonumber(redis.pcall('zcard',KEYS[1])) >= tonumber(ARGV[4]) then return true end;
return false;

2.3 场景三、统计时间窗口内的个数

只统计个数,不做其他的

redis.pcall('zadd', KEYS[1], ARGV[1], ARGV[1]);
redis.pcall('zremrangebyscore', KEYS[1], 0, ARGV[2]);
redis.pcall("expire", KEYS[1], ARGV[3]);
return redis.pcall("zcard",KEYS[1]);

当然在实际落地的过程,会遇到一些其他问题,比如使用lua限制,分布式限制等

有了上面的三个场景后,接下来我们开始实战一个 Starter

三、Starter 实现

3.1 自定义一个 Starter 需要的流程(关键步骤)

  1. 选择一个合理的业务场景。比如我选择了 滑动窗口这个场景。
  2. 创建新的Maven项目,并引入依赖,通常命名需要遵循Spring Boot的命名规范,通常是<your-module-name>-spring-boot-starter
  3. 代码实现,以及其他类的引入
  4. 编写自动配置类。 xxxAutoConfiguration
  5. 编写spring.factories文件, 在src/main/resources/META-INF/spring.factories中注册自定义的自动配置类
  6. 打包并发布到仓库,并在其他项目测试

3.2 本 Starter 的项目工程结构

本文的源码地址:uzong-starter-learning: 学习 SpringBoot Starter 的工程案例

四、代码实现

4.1 lua 脚本

本文给出三个 lua 脚本,分别应对三个场景。

lua 是一种非常简单的脚本语言,如果想了解更多,可以在菜鸟教程中学习,非常轻量:Lua 教程 | 菜鸟教程

4.2 核心逻辑

com.uzong.sliding.window.calculate.CalculateCore

细节描述:

  1. CalculateCore 的创建,需要交给 xxxAutoConfiguration 类。不可在 CalculateCore 上添加 @Resource, @Service 等类。所有 Starter 类的创建都尽量交给 xxxAutoConfiguration,用来控制类的加载。 这是一种规范
  2. 此处依赖 RedisTemplate,DefaultRedisScript、RedisSerializer 等。用例处理接口调用、序列化等。
  3. 调用的是 redisTemplate.execute方法,参数中包含了执行脚本、序列化、业务参数、过期时间等等。最核心也是最基础的接口。用于执行Redis脚本

4.3 对外的 service api

用于上层可以直接使用的 api,目前只提供了3个。对于 api 尽量包含详细的说明。以及注意实现

其实现类,则主要依赖 CalculateCore 类,就不过多介绍

4.4 配置类 SlidingWindowAutoConfiguration

注意细节:

  1. 通过 ConditionalOnClass,否则无法被创建
  2. 通过构造方式在此自动装配类中创建 SlidingWindowServiceImpl 等对象。方便管理所有相关的 bean 对象

4.5 spring.factories

前缀都是 org.springframework.boot.autoconfigure.EnableAutoConfiguration

4.6 打包并发布到仓库,并在其他项目测试

先发布到本地 Maven 仓库,测试没问题,再发布到公司的私服。需要注意版本管理。

到这里,Starter 实战结束了。更多细节可以参考本项目。

执行测试

http://localhost:8080/api/sl/calculateCount?bizCodeKey=001&windowSeconds=10
http://localhost:8080/api/sl/clearOnCondition?bizCodeKey=001&windowSeconds=3&threshold=5
http://localhost:8080/api/sl/keepCalculate?bizCodeKey=001&windowSeconds=3&threshold=5

已同步发布到公众号:面汤放盐 第十节 Starter 实战之 redis 滑动窗口 (qq.com)

掘金账号:第十节 SpringBoot Starter 实战之 redis 滑动窗口 - 掘金 (juejin.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/18819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全】新的恶意软件:无文件恶意软件GhostHook正在广泛传播

文章目录 推荐阅读 一种新的恶意软件 GhostHook v1.0 正在一个网络犯罪论坛上迅速传播。这种创新的无文件浏览器恶意软件由 Native-One 黑客组织开发&#xff0c;具有独特的分发方式和多功能性&#xff0c;对各种平台和浏览器构成重大威胁。 GhostHook v1.0 支持 Windows、Andr…

【MAC】Spring Boot 集成OpenLDAP(含本地嵌入式服务器方式)

目录 一、添加springboot ldap依赖&#xff1a; 二、本地嵌入式服务器模式 1.yml配置 2.创建数据库文件&#xff1a;.ldif 3.实体类 4.测试工具类 5.执行测试 三、正常连接服务器模式 1.yml配置 2.连接LDAP服务器配置类&#xff0c;初始化连接&#xff0c;创建LdapTem…

Android Context 详解

一、什么是Context&#xff1f; Context是一个抽象基类。在翻译为上下文&#xff0c;是提供一些程序的运行环境基础信息。 Context下有两个子类&#xff0c;ContextWrapper是上下文功能的封装类&#xff08;起到方法传递的作用&#xff0c;主要实现还是ContextImpl&#xff0…

python基础-数据结构-leetcode刷题必看-heapq --- 堆队列算法

文章目录 堆的定义堆的主要操作堆的构建堆排序heapq模块heapq.heappush(heap, item)heapq.heappop(heap)heapq.heappushpop(heap, item)heapq.heapreplace(heap, item)heapq.merge(*iterables, keyNone, reverseFalse)heapq.nlargest(n, iterable, keyNone)heapq.nsmallest(n, …

Linux基础学习笔记

目录 1、Linux安装 1.1 安装教程 1.2 Linux目录结构 2、Linux常用命令 2.1 ls 2.2 命令分类 2.3 目录处理命令 2.4 操作文件命令 2.5 查找文件命令 2.6 ln链接命令 2.7 进程相关命令 ​编辑3、配置网络 3.1 关闭windows防火墙 3.2 配置好虚拟机的局域网 3.3 配置…

汇编原理(四)[BX]和loop指令

loop&#xff1a;循环 误区&#xff1a;在编译器里写代码和在debug里写代码是不一样的&#xff0c;此时&#xff0c;对于编译器来说&#xff0c;就需要用到[bx] [bx]: [bx]同样表示一个内存单元&#xff0c;他的偏移地址在bx中&#xff0c;比如下面的指令 move bx, 0 move ax,…

永恒之蓝(MS17-010)详解

这个漏洞还蛮重要的&#xff0c;尤其在内网渗透和权限提升。 目录 SMB简介 SMB工作原理 永恒之蓝简原理 影响版本 漏洞复现 复现准备 复现过程 修复建议 SMB简介 SMB是一个协议服务器信息块&#xff0c;它是一种客户机/服务器、请求/响应协议&#xff0c;通过SMB协议…

dubbo复习:(11)使用grpc客户端访问tripple协议的dubbo 服务器

一、服务器端依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.…

【kubernetes】陈述式资源管理的kubectl命令合集

目录 前言 一、K8s 资源管理操作方式 1、声明式资源管理方式 2、陈述式资源管理方式 二、陈述式资源管理方式 1、kubectl 命令基本语法 2、查看基本信息 2.1 查看版本信息 2.2 查看资源对象简写 2.3 配置kubectl命令自动补全 2.4 查看node节点日志 2.5 查看集群信息…

01 Nginx安装部署(系列篇)

一、安装部署 1、Nginx的发行版本 常用版本分为四大阵营&#xff1a; Nginx 开源版 | https://nginx.org/&#xff1a;赤裸裸的Web服务器、反向代理、负载均衡&#xff08;功能少&#xff0c;开发难度大&#xff09; Nginx Plus 商业版 | https://www.nginx.com/&#xff1a;…

高职物联网专业嵌入式系统开发教学解决方案

前言 随着人工智能与物联网技术的深度融合&#xff0c;物联网&#xff08;AIoT&#xff09;已成为推动产业发展的重要力量。高职物联网专业作为培养技术人才的重要基地&#xff0c;面临着课程体系更新、教学内容优化的迫切需求。嵌入式系统开发作为物联网专业的核心课程之一&a…

[CVPR-24] HUGS: Human Gaussian Splats

本文提出一种新的数字人表征Human Gaussian Splats (HUGS)&#xff0c;可以实现新姿态和新视角生成&#xff1b;本文提出一种新的前向形变模块&#xff08;forward deformation module&#xff09;&#xff0c;在标定空间基于Gaussians表征数字人&#xff0c;并基于LBS学习如何…

秘钥托管技术简介

目录 前言 一、秘钥托管是什么&#xff1f; 二、秘钥托管技术简介 1. Skipjack算法 2. LEAF产生过程示意图 3. 对加密通信的法律实施存取过程 总结 前言 1993年4月&#xff0c;美国政府为了满足其电信安全、公众安全和国家安全&#xff0c;提出了托管加密标准EES (escro…

Aria2下载安装使用

目录 下载Aria2 配置创建 aria2.conf 文件创建 aria2.session 文件 Aria2的使用基础使用多源下载多线程下载后台下载配置文件启动 AriaNg下载安装AriaNg配置AriaNg使用 Tracker 列表 aria2 是一款免费开源跨平台且不限速的多线程下载软件&#xff0c;其优点是速度快、体积小、资…

慧尔智联携纷享销客启动CRM项目 推进客户经营升级与内外高效协作

智慧农业领军企业慧尔智联携手纷享销客&#xff0c;启动CRM客户经营管理系统项目。双方将深入合作&#xff0c;全面落实慧尔智联发展策略&#xff0c;持续提升数字化经营管理水平&#xff0c;实现内部团队信息化高效协作&#xff0c;以快速响应市场需求&#xff0c;提升客户满意…

开源集运wms系统

集运WMS系统是一种专为集运业务设计的仓库管理系统&#xff0c;它能够高效地处理来自多个来源的货物&#xff0c;优化存储和发货流程。 经过长时间的开发和测试&#xff0c;推出了我的集运WMS系统。它不仅具备传统WMS系统的所有功能&#xff0c;还针对集运业务的特点进行了特别…

HNU-计算机体系结构-小班讨论-GoogleTPU的发展历程与思考

因为对GPU比较感兴趣&#xff0c;故选择这个作为汇报课题。

JEPaaS 低代码平台 accessToTeanantInfo SQL注入漏洞复现

0x01 产品简介 JEPaaS低代码开发平台开源版 旨在帮助企业快速实现信息化和数字化转型。该平台基于可视化开发环境,让软件开发人员和业务用户通过直观的可视化界面来构建应用程序 ,而不是传统的编写代码方式。 用户可以在开发平台灵活各个图形化控件,以构建业务流程、逻辑和…

智能合约革命:Web3引领智能化商业的未来

随着区块链技术的日益成熟和普及&#xff0c;智能合约作为其重要应用之一&#xff0c;正在逐渐改变着商业世界的面貌。Web3作为下一代互联网的代表&#xff0c;以其去中心化、加密安全的特性&#xff0c;为智能合约的发展提供了无限可能&#xff0c;将智能合约应用于商业领域的…

使用控制台方式部署sentinel

1.下载控制台jar包 2.运行jar包 java -jar sentinel-dashboard-1.8.0.jar 也可以通过编写批处理文件指定端口、用户名、密码&#xff1a; 客户端添加依赖&#xff08;后续整合springcloudalibaba时不需要此依赖&#xff09; 如修改了sentinel端口&#xff0c;需要添加客户端运…