用户中心是一个独立的服务,管理用户的各种信息和状态,现在要新建一个动态服务,专门收集管理用户的动态,例如“用户王某某几点几分发布了一篇文章”这样的信息流数据。
现在问题来了,在动态服务中如何处理用户数据?
如果仅保存 用户ID 的话,那么在查询动态的时候,还要调用用户中心服务查询对应的用户,这样在展示一个信息流列表的时候就要查很多个用户,其中可能有些用户已经被停用了,需要排除该用户及其动态。
将用户的信息一同保存在动态服务的数据库中,订阅用户中心的相关事件消息,同步修改用户的信息。但是,当在动态服务中新增一条动态的时候,如何保存这些用户信息,是直接保存在每条动态的 Row 中吗,还是用专门的表保存?
如果前者,当用户改名字的时候,还要把所有的动态中名字改过来?
如果是后者,那么还得先判断表中是否已经存在这个用户了?
所以,各位是如何处理这种用户数据呢?
这篇文章中提到了 物化视图 merialized views ,但是并不适合。
总结:应该使用方案1,用方案2的思路解决方案1的问题,那就是监听用户中心的领域事件,当用户被禁用的时候,将其动态数据都删掉,这样就不会出现查出动态数据而对应的用户却被停用的尴尬了。
参考:
Challenge #2: How to create queries that retrieve data from several microservices
A second challenge is how to implement queries that retrieve data from several microservices, while avoiding chatty communication to the microservices from remote client apps. An example could be a single screen from a mobile app that needs to show user information that is owned by the basket, catalog, and user identity microservices. Another example would be a complex report involving many tables located in multiple microservices. The right solution depends on the complexity of the queries. But in any case, you will need a way to aggregate information if you want to improve the efficiency in the communications of your system. The most popular solutions are the following.
API Gateway. For simple data aggregation from multiple microservices that own different databases, the recommended approach is an aggregation microservice referred to as an API Gateway. However, you need to be careful about implementing this pattern, because it can be a choke point in your system, and it can violate the principle of microservice autonomy. To mitigate this possibility, you can have multiple fined-grained API Gateways each one focusing on a vertical “slice” or business area of the system. The API Gateway pattern is explained in more detail in the section in the Using an API Gateway later.
CQRS with query/reads tables. Another solution for aggregating data from multiple microservices is the Materialized View pattern. In this approach, you generate, in advance (prepare denormalized data before the actual queries happen), a read-only table with the data that is owned by multiple microservices. The table has a format suited to the client app’s needs.
Consider something like the screen for a mobile app. If you have a single database, you might pull together the data for that screen using a SQL query that performs a complex join involving multiple tables. However, when you have multiple databases, and each database is owned by a different microservice, you cannot query those databases and create a SQL join. Your complex query becomes a challenge. You can address the requirement using a CQRS approach—you create a denormalized table in a different database that is used just for queries. The table can be designed specifically for the data you need for the complex query, with a one-to-one relationship between fields needed by your application’s screen and the columns in the query table. It could also serve for reporting purposes.
This approach not only solves the original problem (how to query and join across microservices); it also improves performance considerably when compared with a complex join, because you already have the data that the application needs in the query table. Of course, using Command and Query Responsibility Segregation (CQRS) with query/reads tables means additional development work, and you will need to embrace eventual consistency. Nonetheless, requirements on performance and high scalability in collaborative scenarios (or competitive scenarios, depending on the point of view) is where you should apply CQRS with multiple databases.
“Cold data” in central databases. For complex reports and queries that might not require real-time data, a common approach is to export your “hot data” (transactional data from the microservices) as “cold data” into large databases that are used only for reporting. That central database system can be a Big Data-based system, like Hadoop, a data warehouse like one based on Azure SQL Data Warehouse, or even a single SQL database used just for reports (if size will not be an issue).
Keep in mind that this centralized database would be used only for queries and reports that do not need real-time data. The original updates and transactions, as your source of truth, have to be in your microservices data. The way you would synchronize data would be either by using event-driven communication (covered in the next sections) or by using other database infrastructure import/export tools. If you use event-driven communication, that integration process would be similar to the way you propagate data as described earlier for CQRS query tables.
However, if your application design involves constantly aggregating information from multiple microservices for complex queries, it might be a symptom of a bad design—a microservice should be as isolated as possible from other microservices. (This excludes reports/analytics that always should use cold-data central databases.) Having this problem often might be a reason to merge microservices. You need to balance the autonomy of evolution and deployment of each microservice with strong dependencies, cohesion, and data aggregation.
来自Architecting & Developing
复杂度偏高。需要考虑实现风险。
@幻天芒: 主要是根据业务复杂度使用相应的方案,在我的业务中,在动态服务中直接调用用户中心服务是可以接收的。
@蝌蝌: 嗯嗯,那就ok的。只是基础设施要求高些,比如消息队列啥的。
我的思路是直接存储用户ID。也就是1。
在查询动态的时候,操作如下:
1、先查询出动态数据,然后把所有的用户ID取出来
2、通过用户服务,查询这一批用户的用户信息。
3、将1的动态数据与2的用户信息进行组合,汇总会最终的数据。
微服务架构系统灵活性,健壮性,扩展性好,特别适合需求变化迅速的场景。但系统复杂度高,部署,管理难度大。微服务除了开发期框架之外,还有需要一系列的运行期中间件支撑,如API网关,服务注册中心,统一配置中心等。 目前国内比较成熟的吧,东软有一支团队在做, https://platform.neusoft.com/,仅供参考哈
我想应该用第2中方案,
第一张方案还在之前的思想,而不是每个微服务自治,独立进化。
对于数据不一致的问题需要使用最终一致性解决方案。
请问我说的是否正确?