探讨一下微服务,考虑用数据缓存代替服务调用。

2020-04-03 09:54:31 +08:00
 bfbd

全文链接如下:

https://aiportal.github.io/data-driven-service

简单说就是: 每个微服务仅可引用另一个微服务释放出来的数据缓存,不允许直接调用另一个微服务。至于数据缓存何时更新,完全取决于维护该部分数据的那个微服务。

优点: 微服务与微服务之间没有直接调用,不会互相影响,即使某一个或某几个微服务当掉了,其他微服务仍可使用旧版的缓存数据继续运行。

缺点: 设计和划分微服务的时候难度较大,必须让各个微服务之间不依赖同步调用,仅依赖异步数据。

补足: 特殊情况必须做同步调用时,可以用消息队列加等待异步操作完成的伪同步来实现同步操作。

4070 次点击
所在节点    程序员
38 条回复
lhx2008
2020-04-03 10:10:57 +08:00
不知道这个概念是楼主发明的还是。。那写入操作怎么办呢
hebin
2020-04-03 10:16:12 +08:00
这个优点解决的问题现有的方案应该也能解决。 但是这个缺点就很明显了
p2pCoder
2020-04-03 10:18:17 +08:00
事务性系统,几乎没法用
EmdeBoas
2020-04-03 10:22:39 +08:00
一个服务应该有两层:无状态的应用层和有状态的存储层,前者根本不存在挂,有问题替换就行;后者挂了才是真的挂;所以每个微服务的有状态层需要隔离开来;你这样所有服务都去查缓存,存在的问题很致命:
1. 数据都在同一个有状态的服务上,有状态的服务一旦出现问题全都给挂
2. 数据写入 /读取的一致性问题
3. 一刀切使用旧版数据完全脱离业务,很多业务并不能接受过期的数据
gemini767
2020-04-03 10:32:17 +08:00
@hebin +1

缺点不仅仅是异步这么简单,强一致性如何做?高频低效和低频高效的相同数据源,如何划分,多副本存储?感觉为了解决一个问题引入更多问题
kindjeff
2020-04-03 10:36:51 +08:00
槽点有点多吧。上面说的事务性系统没法用之外,即使是逻辑最简单的系统,只要是写多读少,就退化成了没有缓存;如果是读多写少,在调用方那边做缓存不是更简单么,你提到的优点也是一样有。
fox0001
2020-04-03 10:37:41 +08:00
只读的话,CDN 是不是更简单?
guolaopi
2020-04-03 10:40:15 +08:00
MVVM ?
整出了 Vue 的感觉
guolaopi
2020-04-03 10:41:18 +08:00
@guolaopi #8
另:Vue 的双向绑定会引发许多玄学,对比来说的话这种思路也会引发一些玄学
iisky1121
2020-04-03 10:56:18 +08:00
共享缓存,瓶颈不就是在缓存里面了吗?
xuanbg
2020-04-03 12:11:17 +08:00
不客气地说,这个主意真的很糟糕。问题楼上提了一大堆了,我也就不重复了。我来给楼主一个建议,也把我在项目的实践和大家共享一下。

楼主要解决的问题其实是服务不可用时,如何保持数据一致性的问题。

其实这个问题要一分为二地来看,一是必须保证成功的调用,譬如我钱都付了,你不能让我的订单状态还处于待付款状态。二是可以失败的调用,譬如商品中心服务突然调不通了,无法确定商品价格,这个时候就可以返回前端下单失败,让客户等会再来下单。

针对第一种情况,可以用消息队列进行对接。支付中心作为生产者,在客户付款成功后发布一条付款成功的消息到队列,订单服务作为消费者订阅这个队列就行了。如果你担心更新的时候数据库炸了导致更新失败的话,在更新数据发生异常的时候把消息发到延时队列进行重试就好了。

至于第二种情况,那就很简单了,当服务调用失败的时候返回一个错误就行了。一级一级返回回去,用户端总会收到错误消息的。
q8164305
2020-04-03 12:13:40 +08:00
有 mvvm 那味了
nicebird
2020-04-03 14:03:05 +08:00
适合特定只读场景
wellsc
2020-04-03 14:06:08 +08:00
微服务是 stateless 的吧,你这释放缓存的方案,感觉更像是中间件层面的东西了
TransAM
2020-04-03 14:11:24 +08:00
我觉得缓存和不缓存对于调用方最好是透明的,被调用方自己处理缓存的事情,调用方拿着 uri 访问就行。
bfbd
2020-04-03 15:19:16 +08:00
1 、写入操作的问题。
大批量的写入操作就应该封装在本服务内部,而不应该由其他服务承担。如果有,也只能是分层关系,而不应是并列关系。
2 、事务的实现。
可以参考这里:
```
PS: 如果需要实时响应,可以在缓存信息表中增加一个 sync 列,sync 为 true 的 URL 缓存会在资源更新操作 (INSERT, UPDATE, DELETE) 返回前完成部署。
```
[https://aiportal.github.io/etag-cache-service]( https://aiportal.github.io/etag-cache-service)

假设 B 服务的某个资源更新操作需要调用到 A 服务的资源更新操作,当 A 服务的资源更新操作成功返回时,B 服务所需的缓存数据已经部署完毕。同样的,B 服务的更新操作成功返回前,该事务应该提供的缓存数据,也已经部署完毕。
bfbd
2020-04-03 15:24:01 +08:00
@lhx2008

@p2pCoder

关于写入和事务,参见楼上。
kkeiko
2020-04-03 15:30:57 +08:00
你就告诉我,缓存用啥吧。然后用你说的方案解决一下交易问题,就支付宝目前的业务模型。中间有任何一次非本机房的网络调用出问题怎么办?
bfbd
2020-04-03 15:32:32 +08:00
@EmdeBoas

1. 数据只是由一个有状态的服务 (Distribute Service) 负责更新,但数据本身是磁盘上的文件,所以服务挂了没关系,硬盘没挂就可以。
2. 数据的写入,数据的完整性,都由拥有该数据的服务负责,其他服务只能读取。外部服务只能通过消息队列影响本服务的数据。
3. 是的,例如修改密码的操作,用户信息和登录验证层可以是两个服务,总不能让用户无限期等待新密码缓存部署。所以这一块设计了 sync 机制,在密码修改操作返回之前,验证操作所需的缓存就已经部署好了。
这部分内容参见:ETag 缓存服务设计。
bfbd
2020-04-03 15:35:42 +08:00
@fox0001

的确有考虑 CDN,这样就可以超出 docker volume 的系统局限,实现广域网分布式了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/658891

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX