微服务数据库设计与拆分
嫉妒是人性,不因为嫉妒而失态乃至报复则是修养。我们无法压制人性但可以做到有教养。——周国平
请简洁描述 MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?
SQL 标准定义的四个隔离级别为:
·read uncommited :读到未提交数据·read committed:脏读,不可重复读·repeatable read:可重读·serializable :串行事物
单独的数据库:
微服务设计的一个关键是数据库设计,基本原则是每个服务都有自己单独的数据库,而且只有微服务本身可以访问这个数据库。它是基于下面三个原因。
·优化服务接口:微服务之间的接口越小越好,最好只有服务调用接口(RPC或消息),没有其他接口。如果微服务不能独享自己的数据库,那么数据库也变成了接口的一部分,这大大拓展了接口范围。·错误诊断:生产环境中的错误大部分都是和数据库有关的,要么是数据出了问题,要么是数据库的使用方式出了问题。当你不能完全控制数据库的访问时,会有各种各样的错误发生。它可能是别的程序直接连到你的数据库或者是其他部门直接用客户端访问数据库的数据,而这些都是在程序中查不到的,增加了错误排查难度。如果是程序中的问题,只要修改了代码,那么这个错误就不会再有。而上面提到的错误,你永远都没法预测它们什么时候还会再次发生。·性能调优:性能调优也是一样,你需要对数据库有全权控制才能保证它的性能。如果其他部门一定要访问数据库,而且只是查询的话,那么可以另外创建一份只读数据库,让他们在另一个库中查询,这样才不会影响到你的库。
理想的设计是你的数据库只有你的服务能访问,你也只调用自己数据库中的数据,所有对别的微服务的访问都通过服务调用来实现。当然,在实际应用中,单纯的服务调用可能不能满足性能或其他要求,不同的微服务都多少需要共享一些数据。
共享数据:
微服务之间的数据共享可以有下四种方式。
静态表:
有一些静态的数据库表,例如国家,可能会被很多程序用到,而且程序内部需要对国家这个表做连接(join)生成最终用户展示数据,这样用微服务调用的方式就效率不高,影响性能。
读写业务数据访问:
这是最复杂的一种情况。一般情况下,你有一个表是主表,而其他表是从表。主表包含主要信息,而且这些主要信息被复制到从表,但微服务会有额外字段需要写入从表。这样本地微服务对从表就既有读也有写的操作。而且主表和从表有一个先后次序的关系。
跨服务事物:
微服务的一个难点是如何实现跨服务的事物支持。
微服务的拆分:
我们原来的程序大多数都是单体程序,但现在要把它拆分成微服务,应该怎样做才能降低对现有应用的影响呢?
我们用上面的图来做例子。它共有两个程序,一个是“Styling app”,另一个是“Warehouse app”,它们共享图中下面的数据库,库里有三张表,“core client”,“core sku”,“core item”。
假设我们要拆分出来一个微服务叫“client-service”,它需要访问“core client”表。第一步,我们先把程序从原来的代码里拆分出来,变成一个服务. 数据库不动,这个服务仍然指向原来的数据库。其他程序不再直接访问这个服务管理的表,而是通过服务调用或另建共享表来获取数据。
第二步,再把服务的数据库表拆分出来,这时微服务就拥有它自己的数据库了,而不再需要原来的共享数据库了。这时就成了一个真正意义上的的微服务。上面只讲了拆分一个微服务,如果有多个需要拆分,则需一个一个按照上面讲的方法依次进行。另外,Martin Fowler在他的文章'Break Monolith into Microservices'里有一个很好的建议。那就是,当你把服务从单体程序里拆分时,不要只想着把代码拆分出来。因为现在的需求可能已经跟原来有所不同,原先的设计可能也不太适用了。而且,技术也已更新,代码也要作相应的改造。更好的办法是重写原来的功能(而不是重写原来的代码),把重点放在拆分业务功能上,而不是拆分代码上,用新的设计和技术来实现这个业务功能。
微服务的耦合
·时间耦合:客户端和服务端必须同时上线才能工作。发消息时,接受消息队列必须运行,但后台处理程序暂时不工作也不影响。·容量耦合:客户端和服务端的处理容量必须匹配。发消息时,如果后台处理能力不足也不要紧,消息队列会起到缓冲的作用。·接口耦合:RPC调用有函数标签,而消息队列只是一个消息。例如买了商品之后要调用发货服务,如果是发消息,那么就只需发送一个商品被买消息。·发送方式耦合:RPC是点对点方式,需要知道对方是谁,它的好处是能够传回返回值。消息既可以点对点,也可以用广播的方式,这样减少了耦合,但也使返回值比较困难。
下面我们来逐一分析这些耦合的影响。第一,时间耦合,对于多数应用来讲,你希望能马上得到回答,因此即使使用消息队列,后台也需要一直工作。第二,容量耦合,如果你对回复有时间要求,那么消息队列的缓冲功能作用不大,因为你希望及时响应。真正需要的是自动伸缩(Auto-scaling),它能自动调整服务端处理能力去匹配请求数量。第三和第四,接口耦合和发送方式耦合,这两个确实是RPC方式的软肋。
结论:
数据库设计是微服务设计的一个关键点,基本原则是每个微服务都有自己单独的数据库,而且只有微服务本身可以访问这个数据库。微服务之间的数据共享可以通过服务调用,或者主、从表的方式实现。在共享数据时,要找到合适的同步方式。在微服务架构中,数据库的修改影响广泛,需要保证这种修改是向后兼容的。实现跨服务事物的标准方法是Saga。当把单体程序拆分成微服务时,可以分步进行,以减少对现有程序的影响。
面试题积累 https://www.cnblogs.com/skyme/p/13212296.html