简单明了!OLTP场景下的数据分布式设计原则

      最后更新:2020-03-23 12:51:35 手机定位技术交流文章

      前言


      近年来做了分布式项目。很多工作是关于OLTP(在线交易系统)场景中的数据分布式体系结构。在流行期间,这一领域的一些设计和做法刚刚被整理出来。为了避免篇幅过长,本文分为两个部分:设计部分和技术部分。设计部分主要介绍了数据拆分的理论和方法,以及一些原则和经验。技术文章将主要介绍数据库和表格中间件的设计和应用,以及如何构建一个完整的分布式数据服务平台。


      通常是分布式体系结构,应用层分布良好,因为它通常是无状态的(或者通过将数据传输到数据库、缓存、MQ等来实现无状态)。)。只需要在流量条目中添加负载平衡(例如,Nginx、HAProxy、F5),即在应用程序前面,这在大型单体架构中也是可用的因此,一般来说,当我们谈论分布式体系结构时,一个重要的部分是分发数据。


      传统的单一集中式体系结构


      数据分发不像应用程序那样简单,因为每个节点的数据可能不同,路由、多拷贝一致性、甚至多写冲突等问题都需要解决。尽管实现方案很复杂,但数据分发本质上是两个简单的想法:复制和碎片化。复制技术在传统的关系数据库中也很常见,主要用于备份和双重用途,如MySQL复制、Oracle数据保护等。这些片段在数据库中也有相应的产品。例如,MySQL结构和甲骨文碎片化,但是与复制相比,对应于这些数据库供应商的碎片化方案还没有被公众广泛接受。


      通常在NewSQL数据库中使用s-sharding机制构建,它基于paxos和raft算法来确保复制一致性。关于子数据库子表和NewSQL方案的比较和选择,请参考我以前的文章“子数据库子表与NewSQL数据库”


      在OLTP场景中,复制和分段的思想被应用于传统的关系数据库。还有两个更广为人知的名字,它们被分为数据库和表格,并与读写分开


      子数据库子表是对原来的单个数据库表进行拆分,这是实现基于传统关系数据库的分布式体系结构转换的主要途径。因此,第一个问题是:为什么


      会拆分?什么时候需要拆分?


      容量、性能、横向扩展、微服务


      单机数据库存储、CPU、内存和其他资源存在上限瓶颈。当数据量和流量达到一定水平时,性能会急剧下降,也就是说,向上扩展是一个上限,成本相对较高。


      如果要实施横向扩展,需要将原始表的数据拆分为多个物理库表进行存储(水平拆分)


      此外,如果是微服务体系结构,拆分服务属于不同的系统并对应不同的数据库,事实上,它已经被垂直拆分。


      的拆分方法是什么?


      1,垂直拆分


      垂直拆分一般更接近业务拆分方法,这是微服务中最常用的方法。具体拆分将根据DDD(领域驱动设计)技术或业务能力进行。确定了一般的有界上下文,并且分割规则相对清晰。


      对应用程序的侵入性较小。通常只需要配置它们自己的独立数据库(可以是物理机,也可以是不同的实列),以便在选择多个数据源的情况下最多创建一个数据访问层。


      也有垂直拆分的情况,因为热数据和冷数据、同一行数据的不同列具有非常不同的访问频率,或者某些大型字段(如文本和Blob)会影响读写效率,这些列此时也将被拆分到不同的表中。这种方法在一般情况下并不常见,在性能优化中经常被考虑。


      垂直拆分


      垂直拆分优势:


      拆分业务清晰,拆分规则清晰它通常基于以下缺点:系统或交易系统之间的集成或扩展、容易的数据维护、低架构复杂性


      垂直分割:


      某些业务表无法连接。只有在应用层,接口才能用来解决单个库的性能瓶颈,因为每个服务有不同的限制。通常会生成分布式事务场景


      。由于垂直拆分根据服务分类将表分配给不同的库,因此一些服务表会太大,并且会存在单个库的读写和存储瓶颈。需要水平分裂来解决这些问题。


      2,水平拆分


      水平拆分更具技术性,将一个表的数据分布到多个数据库和表。具体的方法可以分为:只划分数据库、只划分表、划分数据库和划分表例如,订单表被分成数据库(ds1 .订单,DS2 .订单...dsk.order),表(ds.order_0,ds.order _ 1...ds.order _ n),以及数据库和表(ds1.order_0,ds2.order _ 1...dsk.order _ n)


      水平拆分


      水平拆分具有以下优点:


      如果操作数据分布在同一个数据库中,它可以支持复杂的SQL,如联接、子查询等。解决单个数据库的性能瓶颈,并支持水平扩展。由于应用程序没有拆分,如果存在分布式数据访问层,则应用程序转换小于


      水平拆分:


      拆分规则,子数据库和子表的数量需要仔细设计。如果涉及多个数据库,在分布式事务场景中的数据扩展过程中将会产生大量的数据迁移工作负载。跨数据库连接通常需要由应用程序来实现。数据库不能直接支持性能较差的数据合并、聚合和分页。


      数据库有分区表、子数据库和子表?


      传统关系数据库的分区表本质上仍然共享cpu和内存,因此它仍然面临着扩展的问题,并且分区表支持的分区键往往不够灵活。然而,一些新的NewSQL分布式数据库,如海洋数据库的分区表,分散在不同的存储节点上,从而避免了单机性能的瓶颈问题


      拆分具体步骤


      1,确定拆分模式


      根据业务特点选择合适的拆分模式,一般结合使用。


      1)垂直拆分


      场景:字段长度、访问频率差异较大的字段表、微服务注意事项:尽量不要拆分需要在同一事务中操作的表


      2)水平拆分


      场景:大量数据。多单表单库性能说明:是否有跨库交易,是否有非拆分键操作表场景,将涉及库表扫描交易


      2,拆分字段


      1)垂直拆分表的确定,字段


      根据功能模块拆分,直接按表。如果要拆分部分列,则有必要添加关联列甚至冗余列


      2)水平拆分字段


      确保所有拆分表都有碎片键,主要是主键或唯一索引,并且这些列需要包含碎片信息如果请求不包含碎片信息,则需要一个全局路由表。


      3,确定拆分规则


      1)范围


      适用于日期、流水标识等业务领域。按照一定的规则按顺序增加。这样,例如,0-9999->;图书馆1,10000 ~ 19999->图书馆2...;20150101-20161231->。图书馆1,20170101-20171231->;图书馆2...


      自然支持水平扩展。冷、热分离归档方便,扩展按需方便,但负载容易不平衡。如果单个仓库的压力很大,也需要数据迁移。


      2)哈希Hash


      数据分布相对平衡。路由通常由mod库/表号计算,这本质上是一种预分配。因此,在扩展过程中需要数据迁移,通常使用一致的哈希和多种扩展方法


      3)应用程序自定义


      应用程序自定义路由规则,配置有与片段标识对应的库表的序列号,可通过路由表、配置文件或其他自定义算法使用该方法具有最高的灵活性,易于实现动态变化。


      在我们的项目中以1、2和3种方式使用


      4,分割数量的确定


      1)假设目标数据量为T(根据业务发展需求估计)


      2)建议p(例如,MySQL为500w),子表数量=T/P


      3)


      4)子库数量=T/L


      库表数量与未来扩展和运行维护要求有关,不应过多或过少。以上主要是从容量的角度来计算的。在实际场景中,还需要综合考虑硬件成本预算、数据清理和归档策略等因素。拆分后如何扩展


      ?在垂直拆分


      1和垂直扩展


      之后,如果应用程序的数据库压力太大,可以通过增加其资源分配(CPU、内存、PCIE)来执行垂直扩展


      2,水平扩展


      水平拆分可以通过添加数据库服务器来扩展此方法需要数据迁移。如果使用一致哈希,将迁移最近节点的数据。如果倍增,所有节点的一半数据将被迁移。


      一致哈希模式,虽然迁移的数据量很小,但很容易造成数据冷热不均。因此,我们项目中采用的具体扩展方式是预先将表分成128个表。在项目的初始阶段,这些表将平均分布在4个数据库服务器中。随着业务数据量的增加,扩展将达到8个数据库。只需要将原来4个数据库的一半表移出到新添加的4个服务器上,然后修改SQL路由。


      双扩展:为了应对整体数据量增长,扩展后的物理机是原来的


      的两倍。如果单个数据库中存在热数据压力,则只能将数据库中的一部分数据迁移出新扩展的数据库。


      单个库扩展:处理切片数据增长过快、扩展到独立物理机


      拆分后的问题


      分布式事务的引入问题跨库连接问题多库合并排序分页问题SQL路由、重写问题多数据源管理问题多维拆分数据聚合查询和其他操作问题

      提供分布式数据访问层摘要库、二级索引库、小表广播


      ,以便在技术文章中详细介绍分布式数据访问层


      读写分离


      在实际的业务场景中,读写数据库的频率是不同的有些人写得多,读得少,例如,交易流程图;有些在阅读和写作上是平衡的,如顺序形式;其他人读得多写得少,如客户、信息和配置信息表


      数据碎片解决了单点性能瓶颈和横向扩展能力,适用于高写入压力的情况。然而,如果能够满足单个库的容量,那么在读多于写少的情况下,通过将读与写分开,可以解决高读取压力的问题。具体来说,写操作可以路由到主库,读操作根据重量、机房等分散在主库和每个从库中。在


      读写分离


      读写分离模式下,需要注意几点:


      1)主从延迟从从属数据库中读取数据存在一定的延迟(通常在毫秒级,当写入压力较高时可能在第二级),因此在选择此方法时,业务应允许一定的数据延迟,例如,此方法通常用于外部查询事务。


      2)在同一事务中,不能从主库中读取数据,因为由于数据延迟,可能会读取脏数据,这违反了事务的一致性,必须从主库中读取。在实际开发中,数据访问层可以根据事务自动提交是否关闭,自动判断是否必须在主库中读取。


      3)对于具有低数据延迟容限的查询事务,可以在开发期间单独封装来自主库查询的接口,或者可以向输入参数添加“强一致性”标志,并且当事务被实现时,用户可以根据该标志从主库中进行选择或者从库中进行读取。


      在实际项目中有一些场景,例如将库划分为表,并将读写分开。然而,重要的是避免将库划分成表格并将读写分开的复杂方案,因为将库划分成表格后读写压力不会太大。


      原则和经验


      数据分发是一项系统工程,需要从领域建模、场景划分、数据访问、数据迁移和扩展等多方面综合考虑。着陆前应该从全球角度进行设计。以下是我们的一些设计原则和经验:


      1)用简单的解决方案解决问题。如果可以,不要分裂,也不要为了分配而分裂。读写分离可以解决这个问题,而不用把库分成表格。


      2)分段必须选择适当的分段规则(这可以确保90%的事务不会跨分段)、整理所有方案,并在实施前提前计划


      3)数据访问层设计得非常强大,但是必须清楚使用场景并避免滥用大脑例如,尽管我们项目中的数据访问中间件支持分布式事务XA,但通常不推荐使用它。支持DDL,但禁止在线交易。支持多库链事务提交,但默认情况下只支持严格的单库事务


      4)要制定应用程序开发规范,明确SQL使用的限制和要求,SQL应该尽可能简单例如,MySQL在我们的项目中使用,并部署在个人电脑服务器上。单台机器性能比小型机器上的DB2和甲骨文差得多。因此,禁止触发器、外键和联接。SQL操作必须带有索引和拆分列(数据访问层也会检查),主键必须是自增的,等等


      5)尝试使用灵活的事务来解决跨库和跨系统的事务问题如果MQ用于最终一致性,则不应使用佐贺和TCC。

      2年9月11日020,北京,全球敏捷运营峰会将迎来今年的第一站!专注于数据库、智能运维、金融科技等领域,与阿里、腾讯、蚂蚁金服、中国银行、平安银行、中国邮政消费金融、中国建设银行、工商银行、农业银行、民生银行、58家园、中国联通大数据、浙江移动、新居网络等技术代表合作。展望云时代数据库的发展趋势,解决运维转型的困境


      2 020 gdevops全球敏捷运营峰会-北京站-白鸽活动

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/2423.html

          热门文章

          文章分类