塔城建设局网站阿里邮箱 wordpress

张小明 2025/12/30 6:10:16
塔城建设局网站,阿里邮箱 wordpress,发布视频的平台大全,wordpress 音乐播放器作为一名有着多年 Java 后端开发经验的技术人员#xff0c;我参与过多个大型 SaaS 系统的架构设计。在这篇博客中#xff0c;我将分享如何设计一个支持多租户的 SaaS 系统#xff0c;重点探讨租户数据隔离#xff08;数据库级别 / 表级别#xff09;和资源配额控制的实现方…作为一名有着多年 Java 后端开发经验的技术人员我参与过多个大型 SaaS 系统的架构设计。在这篇博客中我将分享如何设计一个支持多租户的 SaaS 系统重点探讨租户数据隔离数据库级别 / 表级别和资源配额控制的实现方案。一、多租户架构概述多租户Multi-Tenant是指一个软件系统同时服务多个客户租户每个租户拥有独立的业务空间但共享相同的基础设施。SaaS 系统的多租户架构设计需要解决两个核心问题•数据隔离确保租户之间的数据互不干扰满足安全和合规要求。•资源配额控制每个租户使用的系统资源如存储、API 调用次数避免资源滥用。二、数据隔离方案对比与实现1. 数据隔离方案对比常见的数据隔离方案有三种各有优缺点2. 数据库级别隔离实现架构设计核心代码实现数据源动态切换 /** * 动态数据源路由 */ publicclassTenantRoutingDataSourceextendsAbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { // 从线程上下文中获取当前租户ID return TenantContextHolder.getTenantId(); } } /** * 租户上下文持有者使用ThreadLocal存储租户ID */ publicclassTenantContextHolder { privatestaticfinal ThreadLocalString CONTEXT newThreadLocal(); publicstaticvoidsetTenantId(String tenantId) { CONTEXT.set(tenantId); } publicstatic String getTenantId() { return CONTEXT.get(); } publicstaticvoidclear() { CONTEXT.remove(); } } /** * 数据源配置 */ Configuration publicclassDataSourceConfig { Bean public DataSource dataSource() { TenantRoutingDataSourceroutingDataSourcenewTenantRoutingDataSource(); // 初始化所有租户的数据源 MapObject, Object targetDataSources newHashMap(); for (TenantConfig tenant : tenantConfigService.getAllTenants()) { targetDataSources.put(tenant.getTenantId(), createDataSource(tenant.getDbUrl(), tenant.getDbUser(), tenant.getDbPassword())); } routingDataSource.setDefaultTargetDataSource(defaultDataSource()); routingDataSource.setTargetDataSources(targetDataSources); return routingDataSource; } // 其他配置方法... }3. 表级别隔离实现架构设计核心代码实现表名动态生成 /** * 表名处理器基于MyBatis拦截器 */ Intercepts({ Signature(type StatementHandler.class, method prepare, args {Connection.class, Integer.class}) }) publicclassTableNameInterceptorimplementsInterceptor { Override public Object intercept(Invocation invocation)throws Throwable { StatementHandlerstatementHandler (StatementHandler) invocation.getTarget(); BoundSqlboundSql statementHandler.getBoundSql(); StringoriginalSql boundSql.getSql(); StringtenantId TenantContextHolder.getTenantId(); // 替换表名添加租户前缀 StringmodifiedSql replaceTableNames(originalSql, tenantId); // 通过反射修改SQL FieldsqlField boundSql.getClass().getDeclaredField(sql); sqlField.setAccessible(true); sqlField.set(boundSql, modifiedSql); return invocation.proceed(); } private String replaceTableNames(String sql, String tenantId) { // 简单实现实际应使用正则表达式或SQL解析器 return sql.replaceAll(\b(user|order)\b, tenantId _$1); } }4. 行级别隔离实现架构设计核心代码实现自动注入租户 ID /** * MyBatis拦截器自动注入租户ID */ Intercepts({ Signature(type Executor.class, method update, args {MappedStatement.class, Object.class}) }) publicclassTenantIdInterceptorimplementsInterceptor { Override public Object intercept(Invocation invocation)throws Throwable { Objectparameter invocation.getArgs()[1]; StringtenantId TenantContextHolder.getTenantId(); // 如果参数是实体类自动注入tenantId if (parameter instanceof BaseEntity) { ((BaseEntity) parameter).setTenantId(tenantId); } return invocation.proceed(); } } /** * JPA规范自动添加租户ID条件 */ publicclassTenantAwareJpaRepositoryT, ID extendsSimpleJpaRepositoryT, ID { privatefinal EntityManager entityManager; privatefinal ClassT domainClass; publicTenantAwareJpaRepository(JpaEntityInformationT, ? entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); this.entityManager entityManager; this.domainClass entityInformation.getJavaType(); } Override public ListT findAll() { CriteriaBuildercb entityManager.getCriteriaBuilder(); CriteriaQueryT query cb.createQuery(domainClass); RootT root query.from(domainClass); // 添加租户ID条件 query.where(cb.equal(root.get(tenantId), TenantContextHolder.getTenantId())); return entityManager.createQuery(query).getResultList(); } }三、资源配额控制方案1. 资源配额管理模型设计一个通用的资源配额模型支持多种资源类型/** * 资源配额实体 */ Entity Table(name tenant_quota) publicclassTenantQuota { Id private String tenantId; // 存储配额MB private Long storageQuota; // 已使用存储MB private Long storageUsed; // API调用次数配额 private Long apiCallQuota; // 已使用API调用次数 private Long apiCallsUsed; // 并发用户数配额 private Integer concurrentUserQuota; // 上次更新时间 private LocalDateTime lastUpdateTime; // 资源使用记录方法 publicbooleancanUseStorage(long size) { return (storageUsed size) storageQuota; } publicbooleanuseStorage(long size) { if (!canUseStorage(size)) { returnfalse; } this.storageUsed size; returntrue; } // 其他资源使用方法... }2. 基于拦截器的配额控制实现/** * API调用配额拦截器 */ publicclassQuotaInterceptorimplementsHandlerInterceptor { Autowired private TenantQuotaService quotaService; Override publicbooleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception { StringtenantId getTenantIdFromRequest(request); TenantQuotaquota quotaService.getQuota(tenantId); // 检查API调用配额 if (quota.getApiCallsUsed() quota.getApiCallQuota()) { response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); response.getWriter().write(API调用超出配额); returnfalse; } // 记录API调用 quotaService.recordApiCall(tenantId); returntrue; } }3. 分布式环境下的配额控制使用 Redis 实现分布式计数器确保并发场景下的配额精确控制/** * 基于Redis的分布式配额服务 */ Service publicclassRedisQuotaServiceImplimplementsQuotaService { Autowired private RedisTemplateString, Long redisTemplate; privatestaticfinalStringQUOTA_KEY_PREFIXtenant:quota:; privatestaticfinalStringUSAGE_KEY_PREFIXtenant:usage:; Override publicbooleancheckAndConsume(String tenantId, String resourceType, long amount) { StringquotaKey QUOTA_KEY_PREFIX tenantId : resourceType; StringusageKey USAGE_KEY_PREFIX tenantId : resourceType; // 获取配额 Longquota redisTemplate.opsForValue().get(quotaKey); if (quota null || quota 0) { returnfalse; } // 使用Lua脚本原子性检查并消费资源 Stringscript local usage redis.call(GET, KEYS[2]) or 0 if usage ARGV[1] tonumber(ARGV[2]) then return 0 else return redis.call(INCRBY, KEYS[2], ARGV[1]) end; Longresult redisTemplate.execute( newDefaultRedisScript(script, Long.class), Arrays.asList(quotaKey, usageKey), amount, quota); return result ! null result 0; } }四、多租户认证与权限控制1. 租户识别与认证/** * JWT过滤器从Token中提取租户ID */ publicclassJwtAuthenticationFilterextendsOncePerRequestFilter { Override protectedvoiddoFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException { Stringtoken extractToken(request); if (token ! null) { try { Claimsclaims Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token) .getBody(); // 提取租户ID并设置到上下文中 StringtenantId claims.get(tenantId, String.class); TenantContextHolder.setTenantId(tenantId); } catch (Exception e) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); return; } } filterChain.doFilter(request, response); } }2. 细粒度权限控制使用 Spring Security 实现基于租户的权限控制/** * 租户权限表达式 */ publicclassTenantSecurityExpressionRootextendsSecurityExpressionRoot implementsMethodSecurityExpressionOperations { private Object filterObject; private Object returnObject; publicTenantSecurityExpressionRoot(Authentication authentication) { super(authentication); } /** * 判断当前用户是否属于指定租户 */ publicbooleanisTenantUser(String tenantId) { StringcurrentTenantId TenantContextHolder.getTenantId(); return currentTenantId ! null currentTenantId.equals(tenantId); } // 其他权限方法... Override publicvoidsetFilterObject(Object filterObject) { this.filterObject filterObject; } Override public Object getFilterObject() { return filterObject; } Override publicvoidsetReturnObject(Object returnObject) { this.returnObject returnObject; } Override public Object getReturnObject() { return returnObject; } Override public Object getThis() { returnthis; } }五、方案选择与最佳实践1. 数据隔离方案选择建议2. 资源配额控制最佳实践•分层控制同时实现应用层和基础设施层的配额控制。•预付费机制支持按使用量计费Pay-as-you-go和预付费模式。•弹性扩展当租户资源使用接近配额时提供升级提示。•监控与告警实时监控资源使用情况设置异常使用告警。六、总结设计一个高效、安全的多租户 SaaS 系统需要综合考虑数据隔离和资源配额控制数据隔离• 数据库级别适合对隔离性要求极高的场景。• 表级别平衡隔离性和成本的折中方案。• 行级别适合租户数量庞大的场景。资源配额控制• 设计通用的配额模型支持多种资源类型。• 使用 Redis 实现分布式环境下的精确控制。• 通过拦截器和 AOP 实现透明的配额检查。认证与权限• 从请求中提取租户 ID建立上下文。• 基于租户 ID 实现细粒度的权限控制。在实际项目中建议根据租户规模、数据敏感性和预算选择合适的数据隔离方案并通过弹性的资源配额控制机制确保系统稳定运行。通过上述方案我们成功在多个 SaaS 项目中实现了租户数据的安全隔离和资源的合理分配支持了从几百到数十万租户的平滑扩展。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

新手如何注册网站域名广东的设计公司

第一章:Open-AutoGLM驱动智能制造升级在智能制造加速演进的背景下,Open-AutoGLM作为新一代开源自动化语言模型,正逐步成为工业场景中智能决策与流程优化的核心引擎。该模型融合了自然语言理解、代码生成与多模态数据处理能力,能够…

张小明 2025/12/25 8:43:19 网站建设

做网站入什么会计科目免费h5制作网站

第一章:MCP AZ-500 云 Agent 监控概述在现代云安全架构中,对虚拟机和工作负载的持续监控是保障系统完整性和合规性的核心环节。Azure Monitor 与 Azure Security Center(现为 Microsoft Defender for Cloud)深度集成,通…

张小明 2025/12/28 22:57:48 网站建设

建设银行管官方网站wordpress友情链接主题

在 AI 渗透生活的今天,文本分类早已不是专业领域的 “黑科技”—— 垃圾邮件自动归类、购物评论情感分析、新闻按行业分类、简历关键词筛选,这些场景背后都藏着文本分类的逻辑。对于资源有限(无高性能设备、非专业开发背景)的学习…

张小明 2025/12/25 8:43:15 网站建设

广东手机版建站系统开发wordpress动漫电影主题

智慧树学习助手:自动化网课管理解决方案 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 还在为智慧树平台上的网课学习效率低下而困扰吗?这款智…

张小明 2025/12/25 8:43:13 网站建设

网站国内服务器租用建行业网站的必要性

ncmdump音乐解密工具:轻松解锁网易云加密音乐格式 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 你是否曾经在网易云音乐下载了心爱的歌曲,却发现这些文件只能在特定软件中播放?当你想要在车载音…

张小明 2025/12/25 10:28:42 网站建设

山西建站便宜哪些网站是vue做的

第一章:Open-AutoGLM 与 Sauce Labs 云测试适配差异在自动化测试领域,Open-AutoGLM 作为一种基于大语言模型的测试脚本生成框架,强调本地化智能推理与自然语言驱动的测试用例生成;而 Sauce Labs 作为主流的云测试平台,…

张小明 2025/12/25 10:28:40 网站建设