数据仓库架构(三)数据同步

【摘要】

       数据存储(缓存、数据库、对象存储、大数据、数仓)之间数据迁移和同步。

【背景】

       最近项目在做国产化改造,数据库由mysql迁移到瀚高数据库,记录一下,顺便总结一下以前遇到的各种数据迁移和同步方案。包括redis、mysql(RDS)、memcached、OBS、大数据、数仓 etc.

【问题】

        数据迁移和数据同步(读and写)怎么设计尽量避免数据不一致

【产生数据不一致的原因】

        数据迁移和同步一般都会出现数据不一致,在理想情况下不一致不超过可承受范围即可。有的项目对数据一致性要求较高,1%以上都不可接受,如果存在业务不可中断,或者持续性写入,这种就很难保证1%的数据差异,要做一定的抛弃处理和补救措施。

       高并发条件下产生数据不一致可能有几个原因:

       A、不同线程间网络延迟不同;

       B、分布式架构中往往用数据库和缓存双写,而缓存和数据库不同数据写入请求的速度也不同;

       C、缓存和数据库删除和写入均存在失败的可能性;

       D、数据同步和迁移工具存在丢失数据的可能性;

       E、异源异构数据库迁移,由于数据结构不同而数据不一致;

       F、Kafka、MQ这类数据接入工具,由于数据量太大,写入过于频繁,业务不中断迁移后或多或少地都会不一致。

       G、其他原因待补充ing

【解决方案】

【Memcache和Redis数据同步】

        memcache和redis都可以作为缓存系统,分布式数据库缓存意义是在高并发环境下,为了减轻数据库压力和提高系统响应时间,在数据库系统和应用系统之间增加独立缓存系统。两者对比各有优缺点:

       1、数据类型:memcache只支持简单的key-value结构,而redis支持的数据类型比较多,除了k-v存储,还支持list、sorted、set、string、sorted set、hash等类型;

       2、持久性:memcache不支持持久化;redis有两种方式实现持久化:RDB和AOF,有机会再详细写一下

       3、分布式:memcache的分布方式是客户端哈希分片和一致性哈希两种;redis的分布式就比较多,有多种集群:主从/cluster/sentinel

       4、多线程:memcache支持多线程,redis不支持;

       5、内存管理:memcache写入内存,通过私有内存池/内存池管理;redis不写入内存

       6、事务性:memcache不支持事务;redis有限支持一定的事务性

       memcache缓存数据不能备份,只能用于缓存使用,数据全部在内存中,一旦重启数据会全部丢失,所以在实际使用中一般采用多个memcache的集群,阿里云memcached服务就是这样。其他云如HW现在抛弃了memcached服务,而是全力支持redis服务。memcached迁移redis可以考虑把memcached的多个集群合并到一个redis中,为了提高可用性可以做一个主备。memcache不支持持久化,实际使用中确实会出现重启数据丢失的情况,迁移到redis反而可以避免这个问题。

【Redis和数据库数据同步】

       高可用数据架构中,redis解决了关系型数据库并发量低的问题,有助于缓解关系型数据库在高并发场景下的压力,提高系统的吞吐量。但在实际使用中,缓存与数据库双写难免会出现数据不一致,而两者的数据实时同步方式也会影响数据一致性。读写可以这样设计:

       应用程序读数据:根据key读缓存,如果读取成功则直接返回,如果key不在缓存就根据key读数据库,读取成功后写入缓存再返回。

      应用程序写数据:根据key值写数据库,成功后更新/删除/失效缓存key值

      redis与mysql实时同步方案:

      A、引用Mysql的事务,因为事务有一致性保证,事务提交成功后再更新缓存;

      B、缓存里面引用一些访问控制位,数据库数据变化后,同步更新对应的访问控制位,然后从缓存查询时,优先判断该访问控制位,有变化就从数据库查,无变化直接从缓存返回数据;

      C、通过数据库中间件做缓存和数据库的实时同步;

      双写过程中可能会出现两种性能问题:

      1、穿透:有些key没有在缓存中,可能会引发大量对数据库的查询请求,或者有黑客使用不存在的随机key查询,严重加大数据库的压力,甚至导致数据库服务器的宕机,所以有的项目会把在数据库也查不到的key在缓存中置空,防止对数据库发起重复查询。但是这样会产生很多在缓存和数据库都是空值的key,空值缓存需要更多的键,造成存储空间的浪费;而且用户或攻击者不断发起请求会导致缓存压力过大,导致缓存穿透。

        解决方案:查询缓存前对key进行过滤,只允许系统中存在的key进行后续操作,如采用key的mitmap进行过滤;接口层增加校验,用户鉴权等;缩短无效key的有效时间,防止攻击用户的暴力攻击。

        2、雪崩:缓存中的key一般都会设置有效期,超过有效期则key失效,key的淘汰策略有很多算法,如果key失效或不在内存,程序会重新读取数据库并更新缓存。而如果很多key设置了相同的失效时间或者策略导致批量key失效,会在瞬间产生对不存在key的大量访问,或者缓存重启,造成数据库的请求瞬间爆量,引起大量缓存更新,导致系统性能下降甚至崩溃。

        解决方案:有两种解决策略:

        A、设置缓存数据的过期时间随机,防止同一时间有大量数据过期。热点数据设置为永不过期,开启redis的持久化,当redis重启时从磁盘恢复数据。

       B、搭建高可用redis集群,将热点数据均匀分布在集群中。

【数据库和数据库同步】

        关系型数据库之间的同步一般出现在迁移中,包括本地数据库备份还原、本地数据库迁移至云上数据库、非国产化数据库XC迁移、不同厂商之间云数据库迁移等。

       一般来说,关系型数据库之间的迁移都有自带的工具,或者用云厂商对应的迁移服务,主要是在迁移之前规划好迁移方案。梳理迁移需要的各种配置,包括:当前数据库、版本、集群架构、实例数、数据库数量、目标数据库、迁移方式(全量还是实时,也就是全量+增量)、迁移工具、全量迁移时间等。

       还有一些迁移要注意的事项:

       1、Mysql的迁移原则是迁移至同版本,比如5.6-5.6、5.7-5.7、8-8。

            涉及数据量比较大的同步,需要将目标端数据库的binlog时间修改为0,同时可将innodb_flush_log_at_trx_commit(修改为2)、sync_binlog(修改为500)来提高迁移效率,进入增量后将这两个参数修改为1, binlog时间修改回18小时。

          数据同步任务连接迁移源端主库,不要连接备库,因为某些供应商备库binlog有阉割,会丢失数据。

       2、Mongo的迁移原则是迁移至同个大版本,比如3-3.4、4.2-4.0,高版本向低版本迁移,在一些工具的检查项无法通过。测试库可以每个大版本建立一个实例,源端不同名的库可以迁移在同个大版本的实例下。

         Mongo目前未实现同步模式,无法实现库表名映射功能。

         迁移目标端业务用户需要创建在admin库下面进行统一管理。 mongo4版本每个业务用户需要增加admin库的read权限;mongo3版本每个业务用户需要admin库的read和readAnyDatabase权限才能在本地读取到数据库。

        3、mysql迁移国产化瀚高

         使用瀚高迁移工具进行迁移时,mysql的timestamp和datetime类型转换成highgo的timestamp类型时,生成的timestamp类型时间并不是标准格式,可以手动调整为timestamp(0)

       数据库迁移和同步的方案及注意事项很多,也很复杂,有机会单独写个数据库迁移的,这里就不展开了。

【数据库和数据仓同步】

        是这个项目中遇到的同步问题:数仓ADB和DWS数据来源都是RDS,前台业务一直不断写入,割接前如何保证阿里云和华为云的数据一致?

数据仓库架构(一)数仓产品ADB与DWS-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_53439529/article/details/133922495      我们都知道,数据仓库是不支持事务的,所以数据库是这样设计:业务事务性读写通过关系型数据库RDS,大数据方面的数据接入写入到Hive,然后把RDS和Hive的数据都同步到数据仓。RDS数据同步数仓用数据同步工具DTS(华为云叫DRS),在数据迁移阶段用DRS全量迁移ADB至DWS,增量数据迁移主要是针对RDS,因为业务一直在写数据。

        解决方案:在华为云开一个关系型数据库RDS作为中转,与阿里云的RDS对应,然后两个关系型数据库开DTS数据全量+增量迁移。同时在业务侧做双写,也就是说在割接前保证数据是往两边都写入的,至少可以保证RDS里面的数据在两边是一致的,在阿里云继续用DTS同步RDS数据至ADB,华为云开DRS同步RDS至DWS,这样两边的数仓数据来源一样,数仓里面的数据也一致,割接时只要更改业务侧的双写即可。

【大数据到数据仓同步】

        针对跨集群进行大数据融合分析的场景,导入大数据的Hive数据到数据仓GaussDB(DWS)。Hive是基于Hadoop的一个数据仓库工具,有非常多的公司在用Hive完成数据的离线批处理。Hive可以将结构化的数据文件映射为一张数据库表,并提供类SQL的查询功能。Hive的基本原理是将HQL语句自动转换成MapReduce任务,Hive建立在Hadoop的其它组件之上:

     A、必须依赖于HDFS进行数据存储;

     B、依赖于MapReduceSpark完成查询操作;

解决方案:用HDFS外表导入Hive数据至DWS。

       外表是DWS和大数据建立关联的一种方式,在DWS创建外表导入大数据中的hive数据,其中mrs_server对应的是大数据服务:

CREATE FOREIGN TABLE foreign_product_info
(
product_price integer ,
product_id char(30) ,
product_time date ,
product_level char(10) ,
product_name varchar(200) ,
product_type1 varchar(20) ,
product_type2 char(10) ,
product_monthly_sales_cnt integer ,
product_comment_time date ,
product_comment_num integer ,
product_comment_content varchar(200) 
) SERVER MRS数据源名称 
OPTIONS (
format 'orc', 
encoding 'utf8',
foldername '/user/hive/warehouse/demo.db/product_info_orc/'
) 
DISTRIBUTE BY ROUNDROBIN;

 然后在DWS创建本地表与外表对应:

CREATE TABLE product_info
(
product_price integer ,
product_id char(30) ,
product_time date ,
product_level char(10) ,
product_name varchar(200) ,
product_type1 varchar(20) ,
product_type2 char(10) ,
product_monthly_sales_cnt integer ,
product_comment_time date ,
product_comment_num integer ,
product_comment_content varchar(200) 
) 
with (
orientation = column,
compression=middle
) 
DISTRIBUTE BY HASH (product_id);

外表数据灌入本地表:

INSERT INTO product_info SELECT * FROM foreign_product_info;

【本地和云上对象存储同步】

       对象存储其实也是K-V存储的一种,而且数据湖的底座多是用对象存储,所以这种同步方式也可以在数据湖中发挥作用。

       本地/其他云的对象存储OSS、S3等,可以用对象存储迁移服务,支持多种对象选择方式,包 括文件/文件夹、对象列表、指定对象前缀。

       对象存储可以与流水线和K8S集群配合,做静态网站托管方案:

       1、首先要有一个K8S集群的环境,并且具备云原生的CI/CD能力;

       2、静态网站的前端服务做好工程包,配置好前端服务的流水线;

       3、流水线的最后一步配置推送到对象存储,包括对象存储服务的信息、AK/SK、目录等;

       4、对象存储设置静态网站托管,不同的厂商设置方式不同,这一步如果不做好会直接下载网站的index文件而不是以网页展示;

       5、开一个前端服务的流水线推送测试,确保访问网站没有问题再推送其他。

注意事项:对象存储的本质是一种key-value存储,不具备文件存储那种目录结构,所以推送到对象存储的必须是单个文件。如果网站文件具有明显的目录结构,除非一个一个地推到对象存储,否则只会推送目录第一级的文件,级联文件无法推送过来。

        流水线配置文件级联推送不好实现,可以这样解决:先在原目录打包,然后流水线推送压缩包到对象存储,对象存储可以设置在线解压任务(有的云厂商可能不支持)。要注意在线解压的逻辑和打包的目录结构对应,比如在线解压任务是按照固定的文件名解压,在找不到这个目录的情况下可能解压到根目录,所以在打包原始目录的时候就要注意,和在线解压的逻辑要一致。

   

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值