读 | Software Architecture:The Hard Parts 之耦合
读 | Software Architecture:The Hard Parts 之代码复用
读 | Software Architecture:The Hard Parts 之数据所有权
读 | Software Architecture:The Hard Parts 之数据访问
读 | Software Architecture:The Hard Parts 之事务
读 | Software Architecture:The Hard Parts 之约定
在单体架构中,读数据只要无脑写 SQL 就行,横竖都是怼到一个数据库里,顶多再设计好索引,而当数据分拆到不同的数据库或者由不同的服务控制后,又该如何做?
有 4 种方法可以把数据撮合到一起:
但一个服务需要获取非自己管理的数据时,通过实时调用其他服务来获取信息。这种方式简单直接,但存在几个问题:
可以从其他服务控制的表中拷贝字段的副本到本地表,没有了服务间的交互,取而代之的是在数据层面进行处理。
带来三个问题:
好处就是避免了上一种服务间通信方案中的坏处,适用于数据聚合、制作报表、数据量大、服务响应性要求高、容错性要求较高的情形。
提到缓存时,第一时间会想到两种:本地内存缓存和外置共享缓存服务。前者是不共享的,后者实质上和从另一个服务获取数据类似(只是数据直接存放在内存,少了从物理介质读取到内存的时间,提高了响应性),存在的问题也类似。
副本缓存也是在每个服务的本地放一个缓存,不过这个缓存是其他服务提供的数据的副本缓存,只能读不能写,会持续和源头保持同步。这个领域的产品有 Hazelcast、Apache Ignite、Oracle Coherence 等。
这种方案提供了很好的响应性、容错性、扩展性。需要注意的有以下几个问题:
将需要访问的数据放到一个单独的共享 schema 或 database 里,并且不归属于任何服务。服务之间不用耦合了(服务间没有了约定,但数据库表结构成为了约定),数据的一致性和完整性也得到了保障,存在的问题是共享表结构发生变更时的影响范围变大了、服务有能力访问到不应该它访问的数据、数据所有权没有了归属。