当前位置: 首页 > news >正文

多租户实现方案

实现多租户的话,一般有以下几种实现方案,如下所示:

方案描述优点缺点使用场景
独立数据库每个租户一个独立的DB实例隔离性最好,物理隔离,单租户故障不影响其他人,备份回复容易成本最高(连接池管理,迁移脚本执行),运维复杂,资源利用率低对数据敏感的大客户
独立schema同一个DB实例,每个租户一个Schema隔离性较好,逻辑上分开,运维成本适中跨租户统计困难,数据库连接数有上限,MySQL下Schema过多会影响性能中型SaaS,对隔离有一定要求,且租户数量可控
共享表+租户id所有租户共用一套表,通过tenant_id 字段区分成本最低,资源利用率最高,开发维护简单,跨租户查询容易隔离性最弱,代码层面一旦漏掉租户id,容易造成数据泄露绝大多数saas平台,小微租户多,对成本敏感

我的决策:我会优选采用方案三(共享表+租户ID),因为性价比最高。

技术落地:
一、租户上下文的传递
在网关或者拦截器中,从Header中解析出tarentId,并使用ThreadLocal将TarentId放入当前线程的上下文中;
二、数据隔离的核心
利用Mybatis的拦截器,TenantInterceptor实现他的getTenantId方法

多线程情况下,上下文丢失,导致找不到tenantId;
可以利用spring的TaskDecorator,它允许我们在任务执行前后执行制定逻辑,我们可以通过配置,在任务执行前 设置tarentId,在任务执行后清理

importorg.springframework.context.annotation.Bean;importorg.springframework.core.task.TaskDecorator;importorg.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;public class ExecutorConfig{// 假设这是你用于存储上下文的 ThreadLocal private static final ThreadLocal<String>MY_CONTEXT=new ThreadLocal<>();@Bean public ThreadPoolTaskExecutortaskExecutor(){ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(100);// 关键配置:设置 TaskDecorator executor.setTaskDecorator(newTaskDecorator(){@Override public Runnable decorate(Runnable runnable){//1. 在主线程中捕获上下文数据 String contextValue=MY_CONTEXT.get();//2. 返回一个包装后的 Runnablereturn()->{try{//3. 在子线程中设置捕获到的上下文if(contextValue!=null){MY_CONTEXT.set(contextValue);}//4. 执行原始任务 runnable.run();}finally{//5. 任务执行完毕,清理上下文,防止内存泄漏和数据污染 MY_CONTEXT.remove();}};}});executor.initialize();returnexecutor;}}
http://www.jsqmd.com/news/716682/

相关文章:

  • 强力3个方法:浏览器内GPU加速法线贴图生成的完整指南
  • 生成式AI时代网络管理员的NCCL调优实战指南
  • 分钟搞懂深度学习AI:实操篇:卷积层
  • **TiDB 在高并发场景下的性能优化实战:从慢查询到极致吞吐的跃迁之路**在当前分布式数据库广泛应用的
  • VS Code MCP插件接入实战:3小时完成从零到生产级部署的完整链路拆解
  • [特殊字符] GitHub README 改造接第一单:一个比“AI副业”更具体的小服务
  • SFI立晶ESD/TVS管原厂原装一级代理商分销经销
  • **基于Python的智慧医疗影像分析系统设计与实现:从数据预处理到模型部署全流程实战**在智慧医疗快速发展
  • Java金融事务必须绕开的6个Spring @Transactional陷阱,监管检查高频扣分点逐条标注
  • WCH CH583M-R0开发板与RISC-V微控制器解析
  • 小米开源MiMo-V2.5和Pro模型:高效、低成本,赋能商业级AI应用!
  • **WebSocket实战进阶:从基础通信到实时推送的全流程架构设计与代码实现**在现代Web应用中,**实
  • smolOS:ESP8266上的微型Linux命令行环境解析
  • 边缘设备垃圾检测:NAS优化与TinyML实践
  • 正向+反向+主从解析
  • STC12单片机唯一ID读取实战:三种方法对比与固件版本避坑指南
  • 骑友的修养从第一课开始。骑行,别指指点点,别当让人烦的老师。
  • B站缓存视频转换终极指南:3步实现m4s到MP4的快速无损转换
  • DS4Windows:Windows平台游戏手柄兼容性终极解决方案
  • YOLO26创新改进 | BMVC 2024 | 独家特征融合Neck改进篇 | MASAG多尺度自适应空间注意力门控融合,选择性地突出空间相关特征,助力小目标检测、医学图像分割任务有效涨点
  • 低延迟混合滤波算法原理与优化实践
  • ComfyUI-Impact-Pack:AI图像增强与语义分割的终极工具包
  • 从零启动大模型本地微调,深度解析HuggingFace Transformers+PEFT+Unsloth三剑客协同机制
  • 笔记本CPU温度多少正常?一文看懂正常范围+实时查看方法
  • Jetson AGX Orin升级Jetpack 6.0后,如何优雅地自定义设备树(以关闭PCIe IOMMU为例)
  • 063-基于51单片机四路无线遥控开关【Proteus仿真+Keil程序+报告+原理图】
  • 星铁自动化终极指南:3步解放双手,让游戏自己玩起来!
  • 终极指南:如何用AiZynthFinder快速规划复杂分子的AI合成路线
  • 【DOA估计】基于均匀圆阵相干信号二维doa估计Matlab实现
  • Day07-RNN介绍