分布式数据访问服务之1—华山论剑篇

2023-11-06 18:32

本文主要是介绍分布式数据访问服务之1—华山论剑篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  业界主流的互联网架构中,分布式服务框架、分布式数据访问服务、消息队列服务、服务网关(API)、分布式事务等都是核心的组件和框架。

当我们的系统规模越来越大,从几台服务器扩展到几十台、几百台、上千台,传统的烟囱式的、大集中式系统架构,逐步演进为服务化SOA、分布式的系统架构:

在数据层面,应用层面,访问层面和查询方面,全都以分布式的结构来搭建,使整个系统不存在性能和横向扩展的瓶颈,实现系统的弹性伸缩和横向扩展,

以支撑我们超大规模的系统。

      最近研究了业界主流的分布式数据访问服务,做了一次横向对比和分析。基于对比做技术选型、验证,目的就是要设计一套.Net版本的分布式数据访问组件。

      搞了这么多年.Net,ORMapping(EF、Hibernate、MyBatis),有必要搞一个“分布式数据访问服务”的技术专题,作为总结和技术分享。

      这个系列的第一篇以"华山论剑" 开始吧,细数各门各派的看家本领(分布式数据访问服务框架),一较高低!

一、微软Azure SQL 

使用 Azure SQL 数据库的可缩放工具和功能,可以轻松地横向扩展数据库。特别是可以使用弹性数据库客户端库来创建和管理扩大的数据库。

此功能支持使用成百上千个 AzureSQL 数据库,轻松地开发数据分区应用程序。然后,可以使用弹性作业帮助简化这些数据库的管理。

它包含了三个核心组件:分片映射管理、数据路由、多分片查询

1. 分片映射管理器:分片映射管理器是一个特殊的数据库,它维护一个分片集中有关所有分片 (数据库)的全局映射信息。

2. 数据路由:使用查询中的数据将请求路由到相应数据库的功能

假设将一个请求传入应用程序。基于请求的分区键值,应用程序必须根据该键值判断正确的数据库。接着,它会与数据库建立连接来处理请求。借助数据依赖路由

能够通过对应用程序的分片映射的单个简单调用打开连接,进行数据操作:

3.  多分片查询:多分片查询用于诸如数据收集/报告等需要跨多个分片运行查询的任务。(相比之下,数据相关的路由会在单个分片上执行所有操作。)

当一个请求涉及多个(或所有)分片时,多分片查询将生效。多分片查询在所有分片或一组分片上执行相同的 T-SQL 代码。使用 UNION ALL 语义,

将参与分片中的结果合并到一个总结果集中。该功能是通过该客户端库处理多个任务公开的,其中包括连接管理、线程管理、故障处理和中间结果处理。

最多可以查询数百个分片

总结:微软的Azure SQL是一个PaaS层的数据访问服务,需要将本地数据库迁移到Azure SQL,即云端SQLServer中,

整个Azure SQL支持对SQLServer的横向扩展,在SDK层面简化屏蔽了分库分表带来的一些编程问题,如果采用Azure SQL的话,

分库分表的部署、管理、集成的确非常方便,原生支持。但是本地化私有云环境下,SQLServer的分库分表就需要自己搞了。

二、阿里分布式关系型数据库服务DRDS——云端数据库PaaS服务

DRDS 目前定位成一个中间件(前身是TDDL),在业务应用和RDS(关系型数据库服务器)之间,本身不承担数据存储,

只负责解决分布式情况下数据操作路由、执行、数据处理等功能。主要支持的数据库是MySQL。

DRDS的使用与MySQL非常接近,建实例、建库、建表、SQL操作,唯一比较大的区别在于水平拆分模式下,DRDS对于建表需要指定拆分字段(类似索引),

只要带上这个拆分字段,SQL只会在部分数据分片上执行,从而加速SQL执行速度。

DRDS有着比较完整的MySQL SQL兼容性

DRDS 对于单机事务完整支持,也就是业务中一个事务中的各个SQL最终都落到同一个数据库即可保障强一致,

对于跨数据库的分布式事务,DRDS提供最终一致分布式事务给业务使用,目前处于内测阶段。

1. DRDS基本原理-读写分离:

对于sql进行类型判定,如果判定为读取操作,则按照用户设置的读权重进行sql路由,到主实例或者到只读上进行sql操作。

2. DRDS基本原理-水平拆分

对于sql进行类型判定,如果判定为读取操作,则按照用户设置的读权重进行sql路由,到主实例或者到只读上进行sql操作。

DRDS中的数据是按照拆分字段值,加上特定的算法进行计算,根据结果存储数据到对应分片。

3. DRDS基本原理-SQL路由

当用户SQL到DRDS时,DRDS会解析整个SQL含义,然后按照拆分字段的值和执行策略将SQL路由到对应分区进行执行。

4. DRDS基本原理-数据合并:

如果一个SQL对应多个分片数据执行,DRDS会将各个分片返回的数据按照原始SQL语义进行合并。

5. DRDS支持的SQL语法

6. DRDS不支持的SQL语法:

    受限于分布式事务

  • 跨分片操作, UPDATE/DELETE [ORDER BY] LIMIT

  • 跨分片操作, UPDATE A,B set A.s = B.s+1 WHERE A.ID = B.NAME , 非拆分字段之间的跨库JOIN

  • 拆分键变更, UPDATE A SET A.ID = 1 WHERE XXX, ID为拆分字段

  • 跨分片操作, INSERT A SELECT B WHERE B.ID > XX , 跨库导入导出数据

  • 跨库事务, 比如两次UPDATE不在一个分片上

   子查询限制

  • 暂不支持非where条件的correlate subquery

  • 暂不支持sql中带聚合条件和correlate subquery

7. DRDS是否支持分布式join以及复杂SQL如何支持?

   不是所有的join都能够支持,例如对于大表之间的join,就因为执行代价过高,速度过慢而被DRDS限制,但大部分的join的语义,支持以最高效的方式完成。

   DRDS处理join的原则非常简单:尽可能让join发生在单机

   7.1. 按照同一个维度进行切分:如果能够让join物理上发生在单台机器上,那么任何一类的复杂查询都是可以直接支持的。一般而言,

这就意味着参与join的多张表按照同一个维度进行切分。例如,一个用户有多个商品,每个商品都有自己的商品特征。这时候,如果需要join,可以将所有数据按照用户,

或者按照商品进行切分,那么join就会物理上的发生在同一个机器上,DRDS能够很轻松的保证所有在单机发生的join查询,物理上都能够查出数据,

对于非常复杂的SQL,可以通过注释的方式,直接告知DRDS切分条件,这样就可以绕开SQL解析器进行查询。

  7.2. 小表复制(主数据复制同步):同时可以有选择的将一些不经常更新的,数据量比较小的元数据表复制到全部的节点上。

这样,大表join小表的时候,就从一个分布式join变为了本地join,当然,这种过程需要一定的代价,也就是元数据表内的数据更新,

可能在一小段时间(50~100ms)后才能在分库内看到。

  7.3. 在线查询与离线查询分离:对于复杂的大表和大表的分析和统计类查询,阿里内部推荐采取专门的分析引擎来获取报表数据,比如使用ODPS等,

这类查询使用传统数据库架构,在数据量非常巨大的时候,很可能会影响线上的应用,因此阿里建议将在线和离线查询分开。

总结:阿里的DRDS还是非常强大的,依靠MySQL原生的Replica技术+SQL路由解析+内存数据合并,日常的MySQL分库分表、读写分离等大部分场景都能支持。

三、当当Sharding-JDBC

Sharding-JDBC是当当应用框架ddframe中,关系型数据库模块dd-rdb中分离出来的数据库水平扩展框架,即透明化数据库分库分表访问。

从框架名字看,肯定是Java技术路线的,官方的说明中,Sharding-JDBC功能灵活且全面:

  • 分片策略灵活,可支持=,BETWEEN,IN等多维度分片,

  • 也可支持多分片键共用

  • SQL解析功能完善,支持聚合,分组,排序,Limit,OR等查询,并且支持Binding Table以及笛卡尔积的表查询。

  • 支持柔性事务(目前仅最大努力送达型)。

  • 支持读写分离

Sharding-JDBC定位于日常数据库CRUD操作,目前仅针对DQL和DML语句进行支持

编程示例:

ShardingRule shardingRule = ShardingRule.builder()

    .dataSourceRule(dataSourceRule)

    .tableRules(tableRuleList)

    .databaseShardingStrategy(new DatabaseShardingStrategy("sharding_column", new XXXShardingAlgorithm())) 

    .tableShardingStrategy(new TableShardingStrategy("sharding_column", new XXXShardingAlgorithm()))) 

    .build(); 

DataSource dataSource = ShardingDataSourceFactory.createDataSource(shardingRule); 

  String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?"; 

    Connection conn = dataSource.getConnection(); 

    PreparedStatement preparedStatement = conn.prepareStatement(sql)) {           

      preparedStatement.setInt(1, 10); 

    preparedStatement.setInt(2, 1001); 

      ResultSet rs = preparedStatement.executeQuery();

      {

                while(rs.next()) {

                System.out.println(rs.getInt(1));  

                System.out.println(rs.getInt(2));

        } 

      }

对于复制的综合查询,咨询了当当的架构师团队,他们也在计划通过离线分析和大数据分析来实现,不过其实时性和数据的准确性是一个挑战。

四、Shark:分布式的MySQL分库分表中间件

此Shark非工作流Shark,是云集主要的分布式数据访问框架,也是Java技术路线,它是一个应用程序层的数据访问框架。

Shark的技术优点:

  • 完善的技术文档支持;

  • 动态数据源的无缝切换;

  • 丰富、灵活的分布式路由算法支持;

  • 非proxy架构,应用直连数据库,降低外围系统依赖所带来的宕机风险;

  • 业务零侵入,配置简单;

  • 站在巨人的肩膀上(springjdbc、基于druid的sqlparser完成sql解析任务),执行性能高效、稳定;

  • 提供多机sequenceid的API支持,解决多机sequenceid难题;

  • 缺省支持基于zookeeper、redis3.x cluster作为集中式资源配置中心;

  • 基于velocity模板引擎渲染内容,支持sql语句独立配置和动态拼接,与业务逻辑代码解耦;

  • 提供内置验证页面,方便开发、测试及运维人员对执行后的sql进行验证;

  • 提供自动生成配置文件的API支持,降低配置出错率;

同样,也有很多限制:

  • 不支持强一致性的分布式事务,建议在业务层依赖MQ,保证最终数据一致性;

  • 不建议、不支持多表查询,所有多表查询sql,务必全部打散为单条sql逐条执行;

  • sql语句的第一个参数务必是shard key;

  • shard key必须是整数类型;

项目的Git:https://github.com/gaoxianglong/shark,个人要支持一下,希望能继续增强改进。

五、总结

通过上面四个主要的分布式数据访问服务/框架的比较,我们深入研究了分布式数据访问技术,有以下收获分享给大家:

1. 分布式数据访问组件基于物理上的数据库分库分表,主要解决数据库的横向扩展问题

2. 业界主流的分布式数据访问组件主要面向CRUD操作,复杂查询的实现依赖于数据仓库、分析型数据库、大数据分析等技术来实现

3. Sharding策略和SQL路由是实现分库分表的关键技术,其中Sharding的粒度:主要有两种:Database(数据库) 和 Table(表),即分库和分表

4. Sharding策略主要有以下几种:时间范围、ID哈希、地理区域、Hash分区、枚举分区、表达式计算分区等等

5. 分区键的设计非常重要,阿里的实践值得借鉴:用户和商品两个维度,满足不同用户的需求

6. 分库分表后的复杂查询是一个大的技术挑战:需要解决跨库Join、跨多个Shard查询合并、存储过程、综合BI查询等等,可能需要引入数据仓库和大数据技术来实现

7. 还有分布式事务问题需要解决,阿里有个TXC,可以学习了解借鉴。

综合起来说,分布式数据访问服务是大规模分布式应用的必备中间件,技术复杂度和难度都很高,涉及的技术栈比较多,同时比较深,我们会继续深入研究,

目标是设计一套.Net版本的分布式数据访问服务。有兴趣的小伙伴,可以一起搞

原文地址:http://www.cnblogs.com/tianqing/p/6736320.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

这篇关于分布式数据访问服务之1—华山论剑篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/358335

相关文章

Nginx进行平滑升级的实战指南(不中断服务版本更新)

《Nginx进行平滑升级的实战指南(不中断服务版本更新)》Nginx的平滑升级(也称为热升级)是一种在不停止服务的情况下更新Nginx版本或添加模块的方法,这种升级方式确保了服务的高可用性,避免了因升... 目录一.下载并编译新版Nginx1.下载解压2.编译二.替换可执行文件,并平滑升级1.替换可执行文件

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

pandas数据的合并concat()和merge()方式

《pandas数据的合并concat()和merge()方式》Pandas中concat沿轴合并数据框(行或列),merge基于键连接(内/外/左/右),concat用于纵向或横向拼接,merge用于... 目录concat() 轴向连接合并(1) join='outer',axis=0(2)join='o

批量导入txt数据到的redis过程

《批量导入txt数据到的redis过程》用户通过将Redis命令逐行写入txt文件,利用管道模式运行客户端,成功执行批量删除以Product*匹配的Key操作,提高了数据清理效率... 目录批量导入txt数据到Redisjs把redis命令按一条 一行写到txt中管道命令运行redis客户端成功了批量删除k

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

C#监听txt文档获取新数据方式

《C#监听txt文档获取新数据方式》文章介绍通过监听txt文件获取最新数据,并实现开机自启动、禁用窗口关闭按钮、阻止Ctrl+C中断及防止程序退出等功能,代码整合于主函数中,供参考学习... 目录前言一、监听txt文档增加数据二、其他功能1. 设置开机自启动2. 禁止控制台窗口关闭按钮3. 阻止Ctrl +

java如何实现高并发场景下三级缓存的数据一致性

《java如何实现高并发场景下三级缓存的数据一致性》这篇文章主要为大家详细介绍了java如何实现高并发场景下三级缓存的数据一致性,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 下面代码是一个使用Java和Redisson实现的三级缓存服务,主要功能包括:1.缓存结构:本地缓存:使

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分