如果我们的BaaS为某SaaS提供区块链服务,那么必然面对的就是每个租户的链上数据该如何隔离的问题。在Fabric中,一般来说我们有四种隔离方法,从软到硬分别是:
1.状态数据过滤隔离
我们知道状态数据都存储在一个KV数据库,而我们可以通过构建特定的前缀实现数据存入和数据查询时的过滤。也就是说在ChainCode中,只要是进行PutState时,Key必须是:{租户ID}+“_”+原有Key的格式,这样我们所有的状态数据都是以{租户ID}_开头的,在进行查询时也是,必须保证查询出来的Key带有同样的前缀。如果是有区块链浏览器提供的话,我们也需要给浏览器进行改造,使得在浏览数据前用户必须选择租户ID,然后根据租户ID展示数据。
优缺点:
这样做可以实现一种逻辑上的数据隔离,实际上所有租户的链上数据都存在同一个区块链中,只是根据调解过滤而已,具有数据泄露的风险,还有因为某租户高频交易导致整个区块链交易大量堆积,排队等待打包的情况。而且在浏览器中,用户看到大量的区块,但是点进去却看不到任何交易(因为这个区块里面的交易都不是该租户的),也让人比较迷惑。而且以后想单独把某个租户的所有数据独立出来基本上是不现实的。
2.通道隔离
我们为每个租户都创建一个对应的通道,由于通道与通道之间是数据隔离的,所以可以实现租户之间的数据隔离。这种就不需要在合约上增加租户ID作为前缀,合约编写人员只需要关注业务逻辑即可,不需要关心多租户对合约的影响。而我们要做的就是在SaaS新建一个租户时,在Fabric中也对应新建一个通道,并且安装部署对应的合约。
优缺点:
我们这样做算的上是数据的所谓物理隔离(因为不同通道是不同数据库,或者是磁盘上不同文件夹位置),但是仍然要求各个通道的数据在同一个组织和节点下,所以还不能算真正的物理隔离。另外Fabric对多通道的支持能力比较有限,如果租户有成千上万个,那么就要建那么多通道,怀疑Fabric到时候会不会崩溃。另外合约部署也是,每次建个新的通道就需要建一个对应的合约,所以到时候在一台机器上就可以看到上百上千个一模一样的合约容器实例。
3.组织节点隔离
我们为每个租户创建对应的组织和节点,当然这里我们可以使用新的服务器,如果服务器本身比较强悍,复用现有的服务器也可以。创建好组织节点后,加入现有的Fabric网络,然后创建新的通道,将新组织节点和需要参与相关流程的节点加入到该通道中,然后安装部署合约,创建新的网关,在SaaS中配置新租户对应的新网关的地址。
优缺点:
这样做最大的好处是实现了真正意义上的租户之间的物理隔离,不同租户使用不同的服务器,但是部署非常麻烦,从加入网络、建立通道、部署合约、创建网关等等都需要新做一遍。另外还有一个问题是排序节点仍然是共用的,所以如果成千上万的租户都在发起交易时,排序节点可能成为瓶颈,导致交易堵塞排队等待打包的情况。
4.链隔离
这是终极隔离方案了,每来一个租户,我们就创建一条全新的链,也就是说从机器到所有节点都是独立存在的,每个租户之间没有任何关系,如果真有关系可能就是在同一个BaaS平台上被管理吧。
优缺点:
这么做最大的优点就是彻底的数据隔离,无限的扩展性,理论上来说,不管租户有100W个还是1000W个,他们之间都互不影响。缺点也很明显:1是麻烦,每来一个租户做的准备工作特别多,2是占用资源严重。
总结
由于有这么多隔离方案,所以我们在实际使用中可以将多种方案混合着使用,比如说我们要求物理隔离的情况下,将2通道隔离和3组织节点隔离混合起来用。假如租户ID是一个自增的int类型,那么我们可以按租户ID个位来决定所在的通道,按租户ID的十位和以上部分来决定组织节点的位置。我们在创建一个新组织节点时,自动创建10个通道,然后接下来10个租户就分配到该组织节点的通道中,如果通道满了,又创建一个新组织节点和对应的10个通道,如此循环往复。
另外还需要说的是,不管是哪种隔离方案,我们都应该做到MSP用户的隔离,也就是说在操作合约进行Invoke、Query时,都应该使用本租户对应的用户和证书来处理,而不应该使用同一个MSP用户。