saas化调研

多租户问题

上层业务

平台管理

平台管理功能负责管理租户,比如租户的创建,相关租户资源的分配,比如功能分配(菜单管理管理租户),版本分配等

技术处理

线程获取租户id问题

由用户确定租户,所以可以对前端屏蔽租户概念
租户可以保存到用户登录信息session当中,web层登录时即可获取到,这是初始化节点
简单暴力:封装 SessionUtil.tenantId = RequestContext.getSession().getTenantId()
封装后业务线程即可拿到当前上下文的 租户id,而业务线程触发线程池调用时还是需要调整

关于 threadlocal传递线程池的问题:
两种方式
alibaba ttl
这样的话线程池的问题也能基本得到解决,但是注意wjob等使用的工作线程池,没有requestContext,这类线程池要和其他业务线程触发的线程池隔离开,单独处理传参

综上,我们能拥有的能力是:
非业务线程池仍需要传租户id参数
业务线程池可通过 transmittable等方式拿到租户id
日常编写的业务线程可通过工具类SessionUtil获取到租户id
这应该是所有场景需要获取到租户id的情况了,并且是登录态拿到后就可以获取
RPC调用传参需要看对应的RPC框架实现,但理论上应该都是相同的,只要找到对应的隐式传参方式即可.

关于存储层基础组件的封装

静态数据源
MySQL,TiDB等

表中需要增加租户id(关联表不需要,全局配置比如元数据等也不需要)
例如 Mybatisplus 的租户拦截器,大范围覆盖系统内需要传租户的地方,对于复杂的sql,可以配置不进行租户拦截器拦截,改为手动编写SQL,对于不存在租户id的表同样可配置不进行拦截。

Redis 类KV 存储

K是区分的关键,可以前缀拼 @namespace=tennantId, 即 key = #{tenantId}:bizKey,后面的es,kafka基本也是类似方案,都是在较高层用 namespace 做一个分区

MongoDB

collection tenantId字段

Elasticsearch

基于索引的多租户方案,即每个用户使用不同前缀的一套表,最后基于该套表完成对不同租户的管理。这针对集群规模不算太大时候的场景比较友好,当集群和租户规模过大时,元数据膨胀率会比较高,集群的负载会比较高。
基于索引中的路由进行多租户管理的方案,即所有的用户使用一套表,通过routing来进行数据分发和隔离。这样做的好处是能保持很好的扩展性以及较好的性能,但是缺点是如果在原有代码的基础上改动较大,且按用户删除数据时并不是很方便。

Kafka

基于不同的用户使用不同的topic组分开消费,优点是代码改动较小,只需要配置适配即可,方便资源管理。配合权限管理,可以做到资源隔离。但是缺点是针对部分公用数据的数据膨胀率过高,资源浪费,元数据膨胀率高,用户多的时候集群压力较大。
基于不同的用户使用相同的topic来存储数据,根据不用的key来进行区分和消费。优点是代码改动小,元数据膨胀率可以得到有效控制,适用于多用户的场景。但是缺点是无法做到资源隔离,且消费数据时需要根据key进行判断,影响数据处理效率,不适合大数据高并发处理场景,且没办法很容易地按照用户来单独管理数据。

动态数据源

不考虑了,成本太高,分片应该由存储引擎本身来支持,自己切换动态数据源,那数据倾斜等问题也很麻烦,切换尽量在较小的层面切换,比如能切表不切库之类的,能切库不切节点,能切节点不切集群,切换的粒度小成本会小一些,但确实引入的开发量也会多一些。

工具封装

阶段1支持了业务线程获取租户id的能力,而阶段2存储层的传递命令(sql,redis command key,es index prefix,kafka topic prefix)等都是由当前业务线程发起的,那么就可以在命令发送前,将该租户id 解析进传递的命令当中去作为参数,如前文提到的,第一阶段对解析困难的可以通过手动指定不进行解析,保留原始命令接口,有用户自己进行封装操作(平台管理相关的功能可能需要这种接口)

租户拦截器 较好的开源组件

mybatis plus tenant plugin

主处理流程会对 selectItems, where 子查询,from Items,Join 这四个节点都过一遍才会决定最终要拼的where 条件,拼 where 条件的时候注意 OR 类 表达式的处理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

业务层编码

schema实体类,尽可能的继承公用的 BaseTenantEntity,全局统一租户id的字段名称。
各租户的重点资源数据做逻辑删除。
用户登录时便确定了租户身份,所以只要在登陆前给出不同的租户访问路径即可,见 SAML2.0
单个用户可能拥有多个租户?
userId是否多个租户共享?
SAML2.0 协议下不同的SP是否共用一个用户信息库?
关于 OLTP业务考虑tidb支持(如果CDB能支持tiflash组件,那也可以做olap),关于olap业务考虑es支持,复杂结构化数据mongodb存储?

匹配

直觉上匹配算法应该和图的关联性比较强,暂时不熟悉这块,确实找到的资料比较少
图数据库 Nebula Graph 智联招聘

加密与搜索

存储层做加密

提供加密解密函数,比如 insert encrypt(key)
decrypt(key) like '%partial%
理论上就很困难,比如常见的mysql 索引优势肯定就废了,也就是查询性能会暴跌

分词组合

成本低,效果一般但是是常见手段,tradeoff 吧
就是一串文本分段加密,模糊搜也只能模糊一段
淘宝 https://open.taobao.com/docV3.htm?docId=106213&docType=1
拼多多 https://open.pinduoduo.com/application/document/browse?idStr=3407B605226E77F2
模糊查询字符原文长度必须大于等于4个英文/数字,或者2个汉字,再短的长度不建议支持,因为分词组合会增多从而导致存储的成本增加,反而安全性降低。

理想化方案:译码型加密

高成本,需要懂这一块的人。通过译码的方式保证加密后的与原先的明文语序相同

https://www.jiamisoft.com/blog/6542-zifushujumohupipeijiamifangfa.html

因为是保序的,所以理论上可以走索引类的优化

参考链接
https://juejin.cn/post/7111885028946083871
https://ningyu1.github.io/20201230/encrypted-data-fuzzy-query.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值