Das 位于分层架构 IM 系统中的数据访问层,其在整体架构中的位置,见下图。
Das 的核心职责是封装访问数据库和缓存的接口,为业务逻辑层的 Logic 和 Extlogic 提供获取数据和维护数据的能力。理解 Das 的核心职责并不难,我们需要重点关注 Das 的架构意义。很多同学会有这样的疑惑:在分层架构中,Das 一定是必须的吗?负责处理业务逻辑的 Logic 和 Extlogic 不能直接访问数据库吗?
在分层架构中,中间一层存在的意义,往往是为了解耦。同样的,数据访问层 Das 位于业务逻辑层和数据存储层之间,Das 的架构意义就在于对业务逻辑层和数据访问层进行解耦;解耦之后,Logic 就不知道数据库的存在,数据库的复杂性对 Logic 来说,就完全被 Das 屏蔽了。具体怎么理解呢?
在存储层,为了抗住高吞吐数据读取的压力,我们会为其加一个 “缓存”,将频繁读取的数据放在 “缓存” 中;如果单表的数据量超过上限,我们一般会对数据表进行 “分库分表” 操作;为了进一步优化对数据库的访问,我们会对数据库进行 “读写分离” 操作;当 MongoDB 无法满足业务的事务需求时,我们会将 MongoDB 替换成 MySQL;为了解决 MySQL 集群化问题,我们会将 MySQL 替换成 TiDB 等等等等。 上述存储层任何一个操作在具体落地时都是非常复杂的,如果没有数据访问层的存在,势必会影响到业务逻辑层,而业务逻辑层是进行业务迭代的主体,如果我们正在进行 “分库分表” 的操作,还有精力进行业务的迭代吗?数据访问层,它统统屏蔽了存储层这一系列的复杂性,业务逻辑层只管向数据访问层要数据即可,不用关注存储层的数据存储模式。这就是数据访问层的架构意义。
Das 接收 Logic 的请求后,对数据库进行访问,Das 内部的逻辑结构是怎样的呢?见下图。
Das 内部逻辑结构与 Entry 的逻辑结构很相似(IM专题:分层架构IM系统(5)—Entry设计),整体包括三部分:I/O 线程、请求队列和工作线程池。
I/O 线程通过 “I/O 多路复用” 机制管理多个 Logic 节点客户端的连接;I/O 线程将接收到的 Logic 请求放入 “请求队列” 中;“请求队列” 的下游是 “工作线程池”,其工作线程基于 “数据库连接池” 访问各个业务数据库。这是 Das 内部逻辑结构的工作流程,并不复杂;我们需要重点关注的是 Das 逻辑结构设计中的耦合性问题。
该图中,访问 “云消息库”、“联系人库” 和 “离线消息库” 的请求都会进入到同一个请求队列中,当 “离线消息库” 负载很高时,所有访问该数据库的工作线程会很快进入阻塞等待状态,并耗尽工作线程池中的所有线程;此时访问 “云消息库” 和 “联系人库” 的请求会一直堆积在 “请求队列” 中,得不到及时处理;我们说,离线消息业务影响了云消息业务和联系人业务,这三块业务虽然在数据库维度上进行了物理隔离,但是其耦合性仍然很高。
怎么解决这个问题呢,也就是应该如何解耦呢?为不同的数据库分配不同的请求队列和工作线程池即可,见下图。
I/O 线程将不同的业务请求放入不同的请求队列中,然后由其对应的工作线程池进行处理,这样任何业务数据库的高负载,都不会影响到其它的业务请求了。其实,如此解耦,仍然没有解耦彻底:当云消息业务迭代升级后,我们需要重启 Das 进程,此时联系人业务请求和离线消息业务请求会因为重启而丢失,业务之间仍然存在耦合性。
怎么彻底解耦呢?从进程级别拆分不同的业务请求,见下图。
简单一点描述,就是将 Das 拆分成 cloud_msg_das(云消息 Das)、contacts_das(联系人 Das)、 offline_msg_das(离线消息 Das),如此将三块业务彻底解耦。细心的同学应该会察觉到:这就是从分层架构到服务化架构的演进过程,cloud_msg_das、contacts_das 和 offline_msg_das,都是数据访问层的服务。
最后,总结文中关键:
1、Das 的核心职责是封装访问存储的接口,为业务逻辑层提供获取数据和维护数据的能力;
2、数据访问层存在的架构意义在于解耦业务逻辑层和存储层,向业务逻辑层屏蔽存储的复杂性;
3、Das 的逻辑结构包括三部分:I/O 线程、请求队列和工作线程池;
4、解耦 Das 的逻辑设计:(1)为不同的数据库分配不同的请求队列和工作线程池;(2)从进程级别拆分 Das,即为不同的数据库设计不同的 Das进程。
作者:棕生 | 来源:公众号——架构之魂
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。