[013][缓存模块]基于Redis的计数器缓存模板设计——AbstractCounterCacheTemplate 技术解析

简介: `AbstractCounterCacheTemplate` 是基于 Redis 的轻量级计数器缓存模板,支持原子计数、阈值校验与自动溢出异常(如登录/短信频控)。键可选 MD5 加密,开箱即用,线程安全,适用于分布式限流场景。(239字)

[013][缓存模块]基于Redis的计数器缓存模板设计——AbstractCounterCacheTemplate 技术解析

本项目代码:https://gitee.com/yunjiao-source/tutorials4j/tree/master/framework

1. 概述

在业务系统中,我们经常需要对某个行为或资源的访问次数进行统计,并设定一个上限阈值。例如:

  • 用户每日登录尝试次数限制(5 次)
  • 短信验证码发送频率限制(每分钟 1 次)
  • API 调用配额限制(每小时 1000 次)

传统做法是使用数据库记录次数,但高频计数会带来较大的写入压力。利用 Redis 原子自增特性实现计数器,既能保证性能,又能借助缓存过期机制控制时间窗口。

AbstractCounterCacheTemplate 正是这样一个基于 Redis 的计数器模板抽象类,它继承自 AbstractRedisCacheTemplate<String, Integer>,提供了开箱即用的“计数 + 上限校验”能力。开发者只需继承该类并配置 cacheName,即可获得一个线程安全的、带有溢出异常的计数器。

2. 类结构设计

public abstract class AbstractCounterCacheTemplate 
        extends AbstractRedisCacheTemplate<String, Integer> {
   
    private int maxTimes = 1;
    // 核心计数方法
    public int counting(String key) throws CounterOverflowException;
    public int counting(String key, int maxTimes) throws CounterOverflowException;
    public int counting(String key, int maxTimes, boolean useMd5);
}

2.1 继承体系

  • CacheTemplate<K,V>:顶层接口,定义缓存基本操作(put、get、delete 等)。
  • AbstractCacheTemplate<K,V>:抽象实现,利用 Spring 的 Cache 抽象完成大部分操作,并在 SmartInitializingSingleton 回调中初始化底层缓存。
  • AbstractRedisCacheTemplate<K,V>:指定底层缓存来源为 Redis(通过 CacheManagerCreatorFactory 获取)。
  • AbstractCounterCacheTemplate:进一步限定键类型为 String,值类型为 Integer,并固化计数器逻辑。

2.2 核心属性

属性 类型 说明
maxTimes int 默认最大计数次数,可通过构造或 setter 修改。默认值为 1。

3. 核心方法解析

3.1 值类型与生成器

@Override
public Class<Integer> getValueClass() {
   
    return Integer.class;
}

@Override
public Integer valueGenerator(String key) {
   
    return 1;   // 首次计数时,缓存中存入 1
}
  • getValueClass():告知底层 Cache 实例在 get(key, Class) 时进行类型转换。
  • valueGenerator(String key):当缓存中不存在指定键时,create(key) 会调用该方法生成初始值并存入缓存。计数器场景下,首次计数后次数应为 1,因此返回 1

3.2 计数方法重载

提供了三个 counting 重载方法,最终都委托给最完整的方法:

public int counting(String key, int maxTimes, boolean useMd5) 
        throws CounterOverflowException

执行流程

  1. 参数校验key 不能为 null
  2. 键转换:若 useMd5 == true,则使用 MD5 对原始键进行摘要,以减少 Redis 键的内存占用(适用于键较长、含特殊字符或敏感信息的场景)。
  3. 获取当前计数值:通过 get(newKey) 获取,若为 null 则视为 0
  4. 分支处理
    • 若当前值为 0(即首次计数):调用 create(newKey),内部调用 valueGenerator1 存入缓存。
    • 若当前值 >0:执行 put(newKey, index + 1) 将次数加一。
      • 若加一前的 index >= maxTimes - 1,说明本次操作后次数将 达到或超过 上限,则抛出 CounterOverflowException,异常消息为 String.valueOf(maxTimes)
  5. 返回值index + 1(即本次计数后的新值)。

3.3 异常处理

CounterOverflowException 是自定义的运行时异常,调用方可根据需要捕获并处理(如提示用户“操作次数已达上限”)。

4. 使用示例

4.1 定义具体计数器类

@Service
public class LoginAttemptCounter extends AbstractCounterCacheTemplate {
   
    public LoginAttemptCounter() {
   
        super("login:attempt");        // 指定 Redis 缓存名称
        setMaxTimes(5);                // 设置最多允许 5 次错误尝试
    }
}

4.2 在业务代码中计数

@Service
public class AuthService {
   
    @Autowired
    private LoginAttemptCounter counter;

    public void login(String username, String password) {
   
        try {
   
            int currentTimes = counter.counting(username);
            // 正常登录验证...
        } catch (CounterOverflowException e) {
   
            throw new BusinessException("登录尝试次数已达上限,请稍后再试");
        }
    }
}

4.3 带独立上限的计数

// 动态指定本次计数的上限(例如不同等级的 API 调用方配额不同)
int times = counter.counting(apiKey, 100, false);

4.4 对敏感键进行 MD5 处理

// 原始键可能是手机号、邮箱等隐私信息,使用 MD5 摘要后作为 Redis 键
int times = counter.counting(userEmail, 10, true);

5. 注意事项与最佳实践

5.1 缓存过期策略

AbstractCounterCacheTemplate 本身未设置缓存过期时间,计数会一直累加直到被手动删除或 Redis 内存淘汰。
实际使用时,应利用底层 Redis 缓存的 TTL 能力,例如在初始化缓存时设置过期时间(可重写 create 方法,或在获取 Cache 实例时配置默认过期)。推荐结合 @Cacheableexpire 属性或使用 RedisCacheManager 的默认配置。

5.2 线程安全与原子性

底层调用的是 Spring Cache 接口,对于 putIfAbsentgetput 操作是否原子取决于具体实现。
Redis 缓存实现(如 RedisCache)使用 SET NXINCR 等原子命令。但当前代码逻辑包含 get → 判断 → put 三步,存在竞态条件(两个线程同时 get 到 null,都会执行 create 导致初始值被覆盖)。
如果需要严格的原子性,建议改用 Redis 原生的 INCR 命令并配合 Lua 脚本校验上限。不过对于绝大多数非金融级计频场景,当前实现已经足够。

5.3 键值类型限制

  • 键固定为 String,值固定为 Integer。如果需要计数为 Long 类型(可能超过 21 亿),可修改 getValueClass() 返回 Long.class 并调整 valueGenerator 返回 1L

5.4 溢出语义说明

抛出异常时,缓存中的值已经被加一。调用方可以根据异常信息决定是否进行回滚(例如将计数减一),但通常业务上不需回滚,因为已经达到上限后再计数也应视为失败。

6. 总结

AbstractCounterCacheTemplate 是一个轻量级的、面向业务计数的缓存模板抽象类,它:

特点 描述
开箱即用 继承后只需指定 cacheNamemaxTimes 即可获得完整计数能力
上限保护 达到阈值自动抛出 CounterOverflowException
键安全 支持对原始键进行 MD5 摘要,适合敏感信息场景
灵活重载 可动态传入单次计数的上限值
基于 Redis 利用 Redis 高性能和持久化能力,适合分布式环境

适用场景

  • 登录/密码尝试次数限制
  • 验证码发送频率控制
  • 用户操作配额(点赞、评论、下载等)
  • 开放平台 API 调用频控

改进建议

  • 增加缓存过期时间(可以配合 @CachePutcondition 或自定义 TTL)
  • 考虑提供原子性更强的实现(Lua 脚本)
  • 支持递减或重置计数的方法

通过合理使用该模板,开发者可以快速为系统添加上限可控的计数器功能,同时保持代码简洁和可维护性。

目录
相关文章
|
29天前
|
运维 Kubernetes 应用服务中间件
CI/CD流水线镜像拉取耗时从47分钟降到2分钟,我做了这几件事
换镜像加速源,CI/CD构建从47分钟骤降至2分钟!非代码/硬件优化,仅切换为毫秒镜像(1ms.run)——全源加速(Docker Hub、GHCR、k8s.gcr等),30台服务器10分钟批量配置,失败率归零,凌晨发布成功率100%。
173 16
|
13天前
|
人工智能 小程序 JavaScript
AI开发实战6、抄作业吧!我优化了N遍的go-zero项目AI协作规范文件,一字不差全给你
本文是“AI开发完整项目”系列终篇,详解如何为go-zero微服务自动生成并规范编写CLAUDE.md文档,涵盖项目架构、API规范、代码生成流程及最佳实践,并开源「时光账记」小程序全栈代码供参考学习。(239字)
200 5
AI开发实战6、抄作业吧!我优化了N遍的go-zero项目AI协作规范文件,一字不差全给你
|
29天前
|
Java 大数据 双11
一张图看懂 Java 能干什么——从淘宝下单到双11抢货,背后都是它
本文专为Java零基础小白打造,用通俗比喻讲清Java本质(“万能翻译官”)、跨平台特性及核心优势;解析其在电商、支付等真实场景的应用;破除“Java已死”误区,结合数据说明其持续强势;并给出清晰入门路径与实用学习建议,助你科学起步。
一张图看懂 Java 能干什么——从淘宝下单到双11抢货,背后都是它
|
11天前
|
人工智能 API 数据安全/隐私保护
阿里云 Hermes Agent/OpenClaw 全量部署+百炼API深度配置指南
2026版OpenClaw(原Clawdbot/Moltbot)作为轻量化、高扩展性的企业级AI助手框架,凭借灵活的插件体系和多平台对接能力,成为企业实现办公自动化的核心工具。阿里云百炼作为国内头部大模型服务平台,不仅提供通义千问全系列模型的稳定调用能力,还具备99.9%的服务可用性和企业级数据安全保障,二者的深度集成能让OpenClaw摆脱内置轻量化模型的能力限制,实现智能问答、文案生成、数据分析、代码编写等复杂办公任务的自动化处理。本文基于2026年最新版本实测,结合云端部署与本地Docker部署两种方案,从环境准备、OpenClaw部署、阿里云百炼API配置、功能验证到高级优化,提供包含
198 2
|
28天前
|
弹性计算 人工智能 API
阿里云ECS云服务器快速部署OpenClaw实战|千问大模型Qwen3.6-Plus一站式配置教程
随着AI智能体技术不断成熟,OpenClaw(曾用名Clawdbot)已经成为轻量化、可扩展、高稳定性的开源AI执行框架代表。它能够将自然语言指令转化为真实可执行的系统操作、文件处理、信息检索、流程自动化任务,真正实现从“对话”到“执行”的落地。
631 29
|
6天前
|
人工智能 监控 安全
多模态AI(图像+文本)该怎么测试?不是把图片丢给模型这么简单
本文系统阐述多模态AI测试新范式:突破传统文本测试局限,聚焦图像理解、图文对齐、跨模态推理、幻觉防控、安全注入与鲁棒性验证六大核心维度,提出分层模型、六维测试矩阵及自动化评测体系,强调“证据链”验证——答案必须可追溯至图片真实信息。
|
7天前
|
存储 弹性计算 人工智能
阿里云高校学生专属优惠权益:300无门槛优惠券与学生专属算力包介绍
阿里云通过“云工开物”计划为高校师生提供丰厚专属优惠,包括300元无门槛优惠券、5折教师购买权益及学生专属算力包。300元优惠券适用于全量公共云产品,有效期1年;教师5折权益支持教学与科研;算力包分练手、毕设、科创三档,满足不同学习阶段需求。此外,阿里云还设立了学生优惠券抵用专区,提供一站式资源选购平台,进一步降低学生上云成本。
|
29天前
|
安全 JavaScript 前端开发
React2Shell 漏洞自动化凭证窃取攻击机理与防御研究
CVE-2025-55182(React2Shell)是CVSS 10.0的高危RCE漏洞,可无认证、无交互远程接管Next.js等RSC应用服务器。2026年已爆发规模化自动化凭证窃取攻击,单日入侵766台服务器。本文系统剖析漏洞机理与攻击链,构建检测、监控、防御、响应一体化闭环体系,提供可落地的代码与方案。(239字)
207 16
|
29天前
|
人工智能 安全 搜索推荐
生成式 AI 驱动下网络安全手册重构与防御体系研究
本文探讨生成式AI如何颠覆传统网络安全防御体系,指出其使静态特征检测、固定响应流程和边界信任模型全面失效。文章提出以行为意图识别、持续信任验证和人机协同决策为核心的AI原生安全框架,并提供可落地的代码实现与运营规范,助力组织构建自适应、可解释、有制衡的下一代防御能力。(239字)
123 9
|
7天前
|
存储 数据采集 运维
企业级智能体落地那些难言之隐
2026年,企业级智能体成数字化转型热点,但安全痛点成规模化落地最大瓶颈:数据泄露、合规难适配、技术漏洞、权限失控四大隐患频发。厂商重技术轻安全、企业选型忽视安全评估,导致风险难言、损失难估。安全先行,方为破局关键。
91 0