[033][缓存模块]基于 Redisson 的租户隔离 Redis Key 前缀设计

简介: 本文介绍基于Redisson的多租户Redis Key隔离方案:通过函数式接口`RedisKeyPrefix`与`NameMapper`扩展,自动为Key添加租户前缀(如`tenant1:user:123`),实现无侵入、高性能、可扩展的逻辑隔离,兼容锁/集合等全部Redisson功能。(239字)

[033][缓存模块]基于 Redisson 的租户隔离 Redis Key 前缀设计

在多租户系统中,不同租户的数据必须严格隔离。Redis 作为一种高性能缓存/存储中间件,通常被多个租户共享。一个经典且高效的隔离方案是为每个租户的 Key 自动添加唯一前缀,从而在逻辑上实现命名空间分离。

本文以 tutorials4j 框架中的一段代码为例,分析如何通过函数式接口、Redisson 的 NameMapper 扩展点以及 Spring Boot 自动配置,优雅地实现租户感知的 Redis Key 前缀管理。

一、核心设计目标

  • 无侵入:业务代码只需使用逻辑 Key(如 "user:123"),框架层自动转换为 {tenantId}:user:123
  • 高性能:前缀添加和剥离在客户端完成,无额外网络开销。
  • 可扩展:支持多种前缀策略(仅租户、租户+自定义前缀),方便按业务模块细分。
  • 与 Redisson 无缝集成:利用 Redisson 的 NameMapper 能力,统一处理所有 Key(包括分布式锁、对象、集合等)。

二、租户前缀策略接口:RedisKeyPrefix

RedisKeyPrefix 是一个函数式接口,定义了 Key 的计算规则:

@FunctionalInterface
public interface RedisKeyPrefix {
   
    String SEPARATOR = ":";
    String compute(String cacheName);
}

2.1 租户策略工厂方法

tenant() 方法返回一个基于当前租户 ID 的 Key 生成器:

static RedisKeyPrefix tenant() {
   
    return name -> TenantContextHolder.get() + SEPARATOR + name;
}
  • TenantContextHolder.get() 从线程上下文中获取当前租户标识(通常通过拦截器或过滤器设置)。
  • 生成的 Key 格式:租户ID:原始Key

2.2 租户+自定义前缀策略

tenantPrefix(String prefix) 方法允许在租户 ID 后追加一个固定前缀,便于按模块分组:

static RedisKeyPrefix tenantPrefix(String prefix) {
   
    // 处理 prefix 是否以分隔符结尾,保证格式统一
}
  • 例如 tenantPrefix("order") 生成 租户ID:order:原始Key
  • 不同业务模块(订单、用户、商品)使用不同前缀,有助于监控和管理。

2.3 反向解析:uncompute

由于 Redis 中实际存储的 Key 是带租户前缀的,当需要从外部(如监控工具或手工查询)还原逻辑 Key 时,可使用:

static String uncompute(String key) {
   
    // 去除第一个冒号之前的内容
}
  • 示例:uncompute("tenantA:user:123")"user:123"
  • 该方法是静态工具方法,不依赖具体策略。

三、与 Redisson 的集成:PrefixNameMapper

Redisson 提供了 NameMapper 接口,允许在读写 Redis 时动态改写 Key 名。PrefixNameMapper 是其实现类:

public class PrefixNameMapper implements NameMapper {
   
    @Override
    public String map(String s) {
   
        return RedisKeyPrefix.tenant().compute(s);
    }

    @Override
    public String unmap(String s) {
   
        return RedisKeyPrefix.uncompute(s);
    }
}
  • map:写入/查询时调用,将业务 Key 加上租户前缀。
  • unmap:当 Redisson 需要从 Redis 返回的 Key 反向推导原始 Key 时调用(较少使用,但保持对称性)。

注册到 Redisson 配置后,所有通过 Redisson 客户端操作的 Key(RBucketRMapRLock 等)都会自动应用该映射,实现全自动租户隔离。

四、Spring Boot 自动配置

RedissonConfiguration 负责在 Spring 环境中装配上述组件:

@Configuration(proxyBeanMethods = false)
public class RedissonConfiguration {
   

    @Bean
    @ConditionalOnMissingBean
    PrefixNameMapper prefixNameMapper() {
   
        return new PrefixNameMapper();
    }

    @Bean
    @ConditionalOnMissingBean
    RedissonAutoConfigurationCustomizer prefixNameRedissonConfigCustomizer(
            PrefixNameMapper prefixNameMapper) {
   
        return config -> config.setNameMapper(prefixNameMapper);
    }
}
  • 利用 @ConditionalOnMissingBean 允许用户覆盖默认的 PrefixNameMapper,例如改用 tenantPrefix("custom") 策略。
  • 通过 RedissonAutoConfigurationCustomizer 在不修改 Redisson 自动配置源码的前提下注入 NameMapper

五、租户隔离的效果

假设有两个租户:tenant_1001tenant_1002。业务代码执行:

RBucket<String> bucket = redissonClient.getBucket("user:profile:123");
bucket.set("some data");

实际 Redis 中存储的 Key 分别为:

  • tenant_1001:user:profile:123
  • tenant_1002:user:profile:123

两个租户的数据完全隔离,互不可见。如果某个租户需要清除自己的缓存,可以扫描 tenant_1001:* 模式删除,不会影响其他租户。

六、总结

通过 RedisKeyPrefix 函数式接口加 Redisson 的 NameMapper 扩展点,我们实现了一套轻量、高效、无侵入的多租户 Redis Key 隔离方案。该方案具备以下优点:

  • 透明化:业务代码零改造,只需确保 TenantContextHolder 正确传递租户 ID。
  • 灵活性:可随时切换前缀策略(仅租户、租户+模块前缀等)。
  • 性能:前缀拼接仅发生在客户端,一次内存操作,无额外网络交互。
  • 兼容性:完全兼容 Redisson 的所有功能(分布式锁、集合、队列、发布订阅等)。

对于构建 SaaS 化应用或需要严格数据隔离的系统,这种基于 Key 前缀的租户隔离是一种成熟且高效的实践。

目录
相关文章
|
2月前
|
算法 Java 数据库连接
[011][数据模块]基于雪花算法的 Hibernate 分布式主键生成器设计与实现
本文介绍基于雪花算法的Hibernate分布式主键生成器,支持`@SnowflakeIDGenerator`注解一键集成,自动适配String/Long类型主键,具备全局唯一、趋势递增、高性能等优势,适用于分库分表与微服务场景。(239字)
227 4
|
21天前
|
算法 Java 数据安全/隐私保护
[045][Crypto模块]设计一个可扩展的加解密框架:策略模式与工厂模式实战
本文基于Spring Boot,运用策略模式与工厂模式设计可扩展加解密框架:统一`CryptoProcessor`接口封装AES、RSA、SM2等算法;通过`CryptoProcessorFactory`按枚举类别自动注册/查找处理器;结合Spring自动装配,新增算法(如SM9)仅需实现接口并声明Bean,零侵入扩展。高内聚、低耦合、易维护。(239字)
99 2
|
消息中间件 Java Kafka
什么是Apache Kafka?如何将其与Spring Boot集成?
什么是Apache Kafka?如何将其与Spring Boot集成?
919 5
|
2月前
|
运维 Java 开发者
[015][web模块]基于Spring Boot的HTTP客户端日志与默认配置实战
本文详解基于Spring Boot的HTTP客户端统一配置方案,支持RestTemplate、RestClient与WebClient三种客户端,实现无侵入的日志记录(请求/响应头、状态码)、默认请求头注入(如X-Request-Id)、非2xx异常自动转换及链路追踪支持,全部通过Customizer与Filter机制自动装配,开箱即用,提升微服务调用可观测性与开发效率。(239字)
264 5
[015][web模块]基于Spring Boot的HTTP客户端日志与默认配置实战
|
2月前
|
缓存 NoSQL Java
[006][缓存模块] 两级缓存实战:基于 Caffeine + Redis 的多级缓存设计与实现
本文介绍基于Caffeine(本地)+ Redis(分布式)的两级缓存实战方案,通过自定义`MultiLevelCache`与`MultiLevelCacheManager`,实现Spring Cache标准接口下的透明多级缓存:读优先本地(纳秒级)、未命中查Redis并回填;写同步更新两级,兼顾高性能与数据共享。代码开源可直接集成。
275 0
|
2月前
|
缓存 安全 搜索推荐
[004][缓存模块]Caffeine缓存自定义:构建灵活的Spring Boot缓存管理器
本文介绍Spring Boot中Caffeine缓存的灵活定制方案:通过自定义`FlexibleCaffeineCacheManager`,支持按缓存名(如users/products)独立配置过期策略、容量等参数,兼顾全局默认与个性化需求;结合线程安全创建器、属性合并机制及无缝Spring集成,实现高性能、易扩展、零侵入的本地缓存管理。(239字)
171 2
|
2月前
|
缓存 NoSQL 算法
【Redis】Redis——过期键删除策略、内存淘汰8种策略、LRU/LFU实现
Redis过期删除与内存淘汰是两大核心内存管理机制:前者按TTL自动清理失效键(惰性+定期组合),后者在`maxmemory`超限时主动淘汰键(8种策略,含LRU/LFU近似实现)。二者目标、触发条件与作用范围截然不同,需精准区分与配置。
|
开发者
2024 乘风者计划全新启航!快来加入吧!
 2021年,阿里云开发者社区焕新升级,重磅推出“乘风者计划”!诚邀四海技术博主入驻社区,泼墨云间,书写天地。入驻社区,即可享丰厚权益! 新的一年,乘风者计划重磅升级!
252408 81
|
23天前
|
存储 人工智能 安全
Agent Harness 到底是什么:模型之外的那层控制系统
AI Agent Harness 是包裹大模型的“运行支架”,提供工具调用、记忆管理、权限控制、安全护栏、可观测性与故障恢复等能力,将聪明但无约束的模型,转化为安全、可控、可审计的生产级智能体。
245 1
Agent Harness 到底是什么:模型之外的那层控制系统
|
27天前
|
域名解析 弹性计算 网络安全
从零开始:阿里云服务器购买+配置+建站全流程教程
搭建个人或小型网站,阿里云ECS是稳定可靠的选择,从服务器购买、环境配置到网站部署,全程可按标准化流程完成,无需深厚技术基础。以下从前期准备、服务器购买、初始化配置、运行环境搭建、网站部署、域名解析与备案六大环节,详细拆解全流程,确保新手也能顺利完成网站上线。
435 1