开启左侧

微服务的数据库怎样划分?总不能很多微服务运用同一个数据 ...

[复制链接]
在线会员 2p9KVB 发表于 2023-1-1 09:26:29 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
微效劳的数据库如何分别?总不克不及许多微效劳使用统一个数据 ...

精彩评论5

avatar
在线会员 tkgvdkBWvT 发表于 2023-1-1 09:26:41 | 显示全部楼层
微服务,拆分服务的好处无需多说了。
“但是为什么数据库也必须要拆?”——这其实是很多使用微服务的同学最疑惑的问题了。
数据库拆分不拆分本质上其实就是数据共享的问题。而一个服务一个库本身的观念,其实就是尽最大程度的避免数据的共享。
数据共享会带来如下几个问题:
1、技术实现依然可能耦合

因为没有拆分数据库,所以,很可能一个本来应该独立出来的服务模块,必须依赖于另外的服务模块,而这和我们拆分服务的初衷出现了冲突。
比如,订单服务和个性化推荐服务,很可能都需要访问订单相关数据。此时,如果不拆数据库,则很可能由于订单业务需求导致的订单表结构的修改,倒逼个性化推荐服务也要跟着修改。
2、底层数据的过度暴露

还是上面订单服务和个性化推荐服务的例子,个性化推荐很可能只是需要一些用户 id、订单类别之类的东西,但是由于数据库是共享的,很可能开放的就是订单表的全部数据,而这些数据有很多算是敏感数据,应该被隐藏的,现在则被暴露出去了。
3、无必要的数据访问竞争

因为是同一个数据库,这势必会造成对共享数据的竞争性访问,而这些竞争性访问则会大大影响业务模块的弹性部署。比如,订单模块很可能由于个性化推荐的一些定时批量查询,被影响了其能承载的并发数据量。
所以,看出来了吧,分库是必须要考虑进微服务整个体系结构的。

“一个服务一个数据库”的模式看起来很完美……但是,实际落地来讲,中间有太多的弯弯绕绕了。
比如,我们的服务需要划分成四五十个服务,这个时候,数据库划分成同样的四五十个库就不合适了。因为这会引入如下的三个问题:

  • 数据库管理过于复杂——这个是很显然的问题,管理几个数据库和管理几十个数据库,需要投入的人力物力是完全不一样的。每一台数据库本身就是个很复杂的系统,数量越多,出问题的几率也越大,监控难度也越大。
  • 分布式一致性实现太过复杂——数据库数量上来了,因为业务需要,协调数据一致性从原先需要协调几个数据库的状态变成了需要同时协调几十个。复杂度一下子上去了,这也会造成很多不必要的技术问题。
  • 跨库查询相当不方便——这个问题也是一样的,当我们服务划分后,数据库如果也划分的过细,那么以前需要跨几个库查询的业务,就可能变成需要跨十几个库查询。
所以,就落地的时候来讲,还是需要有个业务域的概念。这也是为什么微服务总和领域驱动设计绑定在一起,因为人家天然有个业务域的概念。
这时候,就可以考虑某些业务域,共享一些数据库。比如,订单业务域可以每个服务对应一台数据库,但是,用户业务域可能就可以共享那么一台数据库。

微服务的数据库怎样划分?总不能很多微服务运用同一个数据 ...
不管是服务的拆分,还是数据库的分库,总的来说,微服务落地是个挺复杂的问题。
更多相关内容可以看一下我的原创文章:
“一学就会”微服务的架构模式:一个服务一个数据库模式(上)我是如何把微服务的这个模式落地的:一个服务一个数据库模式(中)硬着头皮写,硬着头皮搞:一个服务一个数据库模式(下)
回复

使用道具 举报

avatar
在线会员 D8LiO0t 发表于 2023-1-1 09:27:29 | 显示全部楼层
这个问题的没有标准答案,各家怎么做的都有,都有道理,都对。
要回答这个问题,先要回答另一个问题,就是,数据库设计的原则是什么?或者说数据存储设计的原则是什么?而不是把这个问题偷梁换柱成,微服务的数据库如何划分,微服务是对外的展现形式,而数据存储是数据层的存储设计。这是两个完全层面的问题,把这两个问题混在一起,就混淆了基本概念。
回到数据库设计或者数据存储设计的问题。第一个问题就是,准备选用分布式的数据存储设计,还是选用集中式的数据存储设计,还是选用主体集中式存储,加上数据分发的分布式存储设计。
第二个问题是,数据存储设计的时候,是采用第三范式为原则设计,还是选用数据仓库模式进行设计。也就是选用关系网状模型,还是采用事实维度模型。
第三个问题是,这个系统设计主要是事务性的系统,还是查询型的系统,或者说,是olap的还是oltp的。
在把上面三个问题都解答以后,下一步才能走向存储产品的选型,数据同步方案的制定,分布式事务方案的设计,然后才到程序设计这一步,才能到微服务如何和他们结合一起工作的问题。
现在的大部分公司受互联网行业的影响,已经没有专门的dba这个岗位了,所以以前属于数据架构师需要分析解决的问题,现在一股脑推给应用架构师来尝试解决。却缺乏最基本的理论知识储备。
瞎搞。
回复

使用道具 举报

avatar
在线会员 8ajhK4E 发表于 2023-1-1 09:28:20 | 显示全部楼层
第三方支付就是一个比较好的微服务案例,来说明这个问题

比如微信支付,它跟我们的业务系统合并在一起,提供对外的服务。
但微信支付有自己的数据库的,我们传递给微信支付的字段里面,用户名,id,商品名称,详情,折扣信息均有,完全是一套新系统的做法。
因此,每个微服务,都能独立对外的。这个视角非常重要,否则无法做到微服务。
回复

使用道具 举报

avatar
在线会员 7s4v 发表于 2023-1-1 09:29:12 | 显示全部楼层
多维度架构之微服务的服务拆分

netkiller:多维度架构之微服务的服务拆分<a href="http://www.zhihu.com/club/1241768772601950208" data-draft-node="block" data-draft-type="link-card" data-image="http://pic1.zhimg.com/v2-92b3e2f60392f191a895e5704ad1d7f4_120x160.jpg" data-image-width="720" data-image-height="960" class="internal">多维度架构 - 知乎最近在群里有人问关闭分布式事务的话题,详细听了他们需求后。我呵呵一笑,大约在15年前我就遇到过这种问题。
起因是这样的,这是一个电商系统,架构师给出的架构是这样的:

  • 用户中心:负责用户注册,登录,用户信息,钱包管理……
  • 商品中心:负责商品的管理,包括展示,价格和库存管理……
  • 广告中心:负责商品推广,促销……
  • 物流中心:负责订单的物流……
  • 等等中心:负责等等……

每个中心都有一个独立域名例如:

  • user.domain.com
  • product.domain.com
  • ad.domain.com
  • ……
这种架构设计会存在一个问题,用户每下一个订单,都需要连接多个中心,做一连串调用,最终完成下订单这个功能。因为用户可能操作过程中终止购物流程,或者不可抗因素导致流程无法继续。为此需要设计了一种分布式事务系统,用来解决事务回滚的问题。
所谓的分布式事务,是指跨服务器实现数据库生成与回滚操作,例如:用户购物,浏览商品,添加购物车,选择物流方式…… 这些数据产生在不同服务器上,如果用户取消订单,数据将依次反向回滚。
无独有偶,另一个跨境电商公司的同事也遇到了这种问题,苦苦找不到解决方案,想起了我,询问我的意见。
有时候你会发现,人们会陷入思维边界的陷阱,全力以赴在错误的方向上,无法自拔。

  • 首先,划分中心的架构思维,之所以会出现这种划分方法,我认为跟我们的教育方式有关,导致了多数人都会沿用这种思维定式。
  • 其次,分布式服务的确能解决他们遇到的问题,能想到分布式事务,证明他们智商没有问题。但分布式事务不是最优解,是最差解决方案。
  • 最后,出现了南辕北辙,在错误方向的道路上越走越远。
大约在15年前我们也遇到了这个问题,幸好我及时出手纠正了架构设计的误区,从而没有走上分布式事务之路。
那时还没有微服务的概念,也没有容器技术,我们主要使用物理服务器,在服务器上运行多个实例。从BAT高薪挖来的架构师的思路跟上面一样,将应用划分成各种心中,并且要求每个中心都部署在独立物理机上。划分中心这种方式也与当时的开发模式有关,采用敏捷开发,分成多个小组,每个小组负责一个中心,小组间定义好信通接口,然后所有小组马力全开,活就一起开干了。现在想想简单又粗暴,就如人体器官一样,五脏六腑的联系不是通过一条神经实现的,他们的联系十分复杂。所以我们不能单独思考每个中心,然后就认为把它们合起来就是一个整体。
netkiller:办公室工位必备装备成本控制
随之时间推移,服务器用量越来越多,且服务器上运行的实例长时间都达不到 20% 资源利用率。为此我们开始尝试刀片服务器,和多实例+负载均衡方式运行。
运维的挑战
每个中心都需要与其他中心通信,配置文件非常复杂,这给运维带来不小负担。为此我们开发自动化发布系统。
故障排查难点
因为参与的节点多,系统每天都会出现各种问题,同时每次故障排查及其耗时。
例如每个节点都会产生日志,排查故障时,要一个节点一个节点检查。看查看所有节点上的日志。为此我们开发了一个日志同步程序,能够增量和差异同步日志到日志中心。
如果再继续下去,我们一定会去研发分布式事务。
此时有一个更好的机会等着我,于是我提出了离职申请,反证是准备离开了,也不怕得罪人,我想我应该在离职之前把这些问题跟公司说一下。
我向公司反映了目前面临的所有问题,并且提出了两个概念:

  • 基于工作流拆分服务:服务的拆分法则,基于工作流拆分服务,确保该工作流运行在一个实例中。
  • 服务器即是服务池:所有物理机应该是一个服务池,根据我们的需求,可以将它部署成任何服务。
netkiller:买「蓝牙降噪」耳机「不纠结」基于工作流拆分服务

上面提出的两点,直到今天也仍然适用,例如在微服务的拆分中。在我的职业生涯中,这两个概念始终在指导我的团队。下面我详细说明两个概念怎样应用到实际的工作中。
我们还以电商系统举例,用户下单购物的工作流,如果是按照中心划分,流程可能是这样的:
用户 —> 商品中心(浏览) —> 搜索中心(过滤)—> 用户中心(添加购物车)—> 物流中心 (物流方式) —> 结算中心(支付结算/扣积分)—> 商品中心(扣库存)—> 用户中心 (完成)
数据流在,商品中心,搜索中心,用户中心…… 服务器中不断传递,网络延迟,网络超时,网络故障等等任何错误都可能影响用户体验。
如果是运行在一个实例中呢?确切的说,我们需要让工作流运行在一个服务器上,一个CPU、内存和硬盘上。这样就没有分布式事务的需求了,数据库的事务处理解决了所有的问题,就这么简单!!!
基于这种法则,我们将几套工作流归类,放在一个实例中,放在今天就是微服务。同样微服务的拆分也尽量满足一套工作流在一个微服务客户端上,避免请求过程出现,一个微服务调用另一个微服务的情况。
netkiller:买 MacBook Pro 还是 iMac?服务池的概念

服务器即是服务池的意思是,做到服务于服务器无关,与IP地址无关,通过运维手段,可以将服务器部署成任何服务,这样可以最大化利用硬件资源,不至于一些服务器资源闲置,而另一些则满负荷工作。这样更容易调配服务器资源。
这种概念在今天的容器中得到了更好的实现。
netkiller:怎样选择折叠自行车?最后总结

还是那句话架构设计是做减法,不是堆技术。你需要从整体考虑,整体不等于个体的总和,这就是多维度思维。
分布式事务目前有成熟的解决方案,但是能不用在高并发,长工作流的需求上,这种方案增加了系统的复杂度。导致开发复杂,测试难度大,运维难,故障多。
更多架构知识请关注作者系列电子书《Netkiller Architect 手札》
netkiller:多维度架构之消息队列netkiller:多维度架构之超时时间netkiller:多维度架构之网络损耗netkiller:多维度架构之会话数多维度架构之分库分表

netkiller:多维度架构之分库分表分库和分表是架构必经之路,我想问问你是怎么分库和分表?
很多系统在设计之初就没有考虑过后期的分库与分表,甚至开发团队没有架构和DBA人员,开发团队也比较年轻,对于数据库的架构定义非常随意,满足当前需求即可。
实际上数据库结构等同于建筑里面的地基,地基没有打好,后面的优化都是徒劳的,最终不得不重构数据库结构。
那么你是怎样分库分表的?

任何系统数据流都是漏斗形状的,数据库是漏斗末端,架构设计是尽量在前端计算,合并,拆分,分流,缓存,最终将有价值的数据写入数据库。数据库的访问是结果集越小越好。
基于这种认识,通常分库和分表,我们想到的就是首先垂直分表,这种方式简单易操作。
  1. 当前(本年度数据库)(热数据)
  2. 2019年数据
  3. 2018年数据
  4. 以此类推
  5. 或者按照月份分表
  6. 当前(热数据)
  7. 10月数据
  8. 9月数据
  9. 以此类推
复制代码
这样分表可以缩小结果集,能快速解决查询瓶颈问题。但是新的挑战来了,由于分表后,索引是独立不连续的,历史数据的查询或遍历数据变的复杂了,要么使用联合查询,要么一张表一张表的遍历。
同理水平分表也是粗暴的将一些尺寸较大的列独立成新表,以降低单个表的容量尺寸。
如果是单纯的数据查找,还是能忍受,我们可能根据时间来选择查询的表,如果是复杂的SQL操作,就只能逐一查询,在程序中二次计算,合并等等操作。
这种分库或分表的思路,理论上属于数据归档。将热数据放在当前数据库中,将很少查询的冷数据放在另一个库中。但是对于 user 这种表就无能为力,你不知道那个用户什么时候会做登录操作。
分表需要从业务角度考虑

分表需要从业务角度考虑,数据库服务于业务逻辑。
由于我即负责产品也负责架构,长期的工作中,总结出一套分库分表的策略。

我分表策略是:

  • 从UI角度出发
  • 从业务流角度出发

举例一,用户表分表?


用户表怎样水平拆分呢? 用户登录的逻辑是这样的,第一个UI 输入用户名和密码,提交后验证密码,用户是否过期,记录登录时间,IP地址。第二个UI,载入用户资料,包括用户姓名,年龄,性别等等…..
数据库我是这样设计的:
  1. +-----------------------------------------------+
  2. | Member                                        |
  3. +-----------------------------------------------+
  4. | id | username | password | ip | ctime | mtime |
  5. +-----------------------------------------------+
复制代码
就这么简单,会员表服务于第一UI
  1. +-----------------------------------------------+
  2. | Profile
  3. +-----------------------------------------------+
  4. | id | member_id | name | sex | age | mtime |…… |
  5. +-----------------------------------------------+
复制代码
服务于第二个UI,通过 member_id 关联数据
怎么样?用户登录过程并不会去访问 profile 表,只有登录成功才会访问。
用户表怎样垂直拆分呢? 将 username 做crc32/md5/sha1 运算,使用哪种随你,取出第一个字符用于分表。
例如 neo, netkiller 两个用户被分到 member_n 表中,jerry,jam 被分到member_j 表中,与支配套的还有 profile_n, profile_j 等等。我们甚至还可以使用外键约束 member_n 和 profile_n 两个表。
当用户登录是,对用户ID做一次 hash 运算,就知道去哪个表中找到该用户的数据。
举例二,商品表如何分表?

商品信息表数据量非常大,我们可以基于品类分库或分表,我们UI设计中,一般只有首页才会将不同分类的产品聚合到一起。进入品类分类页面后,只会访问该品类的数据表。
这就是从业务流的角度进行分表,用户操作是逐渐被引导至我们想呈现的页面。
举例三,海量用户如何分库?

海量用户分库的思路是,用户被分配到指定数据库,该用户所有的数据都会产生在该数据库中,也可以理解为基于数据库隔离用户。
基于该思路分库,这样表名保持不变。
例如 neo, netkiller 被分配到 schema_n.member, schema_n.profile
例如 jerry, jam 被分配到 schema_j.member, schema_j.profile
一旦用户登录,便被锁定到指定的数据库,接下来所有操作,用户产生的数据,都被存储在该数据库中。索引连续,外键约束,触发器,存储过程,均不影响使用。
使用分区表
使用分区别将分区数据写入挂载的SSD盘上。例如 /opt/data/ 下面挂载了四块SSD,目录名是 partition1~4。
  1. CREATE TABLE your_table (id INT, cdate DATE) engine='InnoDB'
  2. PARTITION BY LIST(YEAR(cdate)) (   
  3.     PARTITION p2020 VALUES IN (2020)  DATA DIRECTORY = '/opt/data/partition1',        
  4.     PARTITION p1999 VALUES IN (1999)     DATA DIRECTORY = '/opt/data/partition2',
  5.     PARTITION p1998 VALUES IN (1998)     DATA DIRECTORY = '/opt/data/partition3',
  6.     PARTITION p1997 VALUES IN (1997, 1996, 1995)     DATA DIRECTORY = '/opt/data/partition4'
  7. );
复制代码
最后总结

分库和分表不是简单的切割,而出需要从业务的角度出发,从产品经理视角,你需要展现什么数据,什么样的数据库结构能更好的为UI服务。或者我们应该设计什么样的UI才能更好的展现数据。
多维度架构的核心就是跨界,用跨界知识解决架构中存在的问题。
回复

使用道具 举报

avatar
ico_lz  楼主| 2p9KVB 发表于 2023-1-1 09:29:37 | 显示全部楼层
一般来说,微服务有自己的私有数据库,不能直接访问别的微服务的数据库。也不让别的微服务直接访问自己的数据库。因为微服务的目的是要独立演进,如果数据库被别人访问了,需要修改数据库表结构的操作就会非常的难(各服务之间就耦合在一起了)。
微服务之间的读操作一般直接调用对方微服务的接口。写操作一般发消息给其它微服务(EDA)。
一般来说,每个微服务维护自己的cache,不要cache其它微服务的数据。因为你不知道数据什么时候会被修改过期。而且cache太多份也浪费内存。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 qq_login

本版积分规则

发布主题
阅读排行更多+
用专业创造成效
400-778-7781
周一至周五 9:00-18:00
意见反馈:server@mailiao.group
紧急联系:181-67184787
ftqrcode

扫一扫关注我们

Powered by 职贝云数A新零售门户 X3.5© 2004-2025 职贝云数 Inc.( 蜀ICP备2024104722号 )