【大厂技术内幕】字节跳动原来是这么做数据迁移的!(上)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 【大厂技术内幕】字节跳动原来是这么做数据迁移的!

数据迁移

目标

  • 能够描述项目数据迁移的方案
  • 了解hbase的特点
  • 能够熟悉数据迁移中的数据包装和转换
  • 能够完成文章数据的全量和增量迁移
  • 能够完成热点文章数据的迁移

1 为什么需要自动同步

因为MySQL保存着我们爬取的以及自建的数据,对于爬取的数据,数据量比较大,使用mysql 存储会影响mysql的性能,并且我们需要对数据进行流式计算,对数据进行各种统计,mysq满足不了我们的需求,我们就将mysql中的全量数据同步到HBASE中,由HBASE保存海量数据,mysql中的全量数据会定期进行删除。


HBASE中保存着海量数据,我们需要计算出热点数据,并将数据同步到mysql以及MONGODB中,mysql中保存主体关系数据,MONGODB保存着具体数据信息。


因为热点数据也会失效,今天是热数据,明天就不是了,也需要定期对热点数据进行删除,我们定时删除一个月之前的热点数据,保持本月的热数据。

2 迁移方案

2.1 需求分析

2.1.1 功能需求

有了大量数据集基础后,实时计算后的热点数据需要保存起来,因为mysql保存大量文章数据会影响mysql的性能,所以采用mysql+mongoDB的方式进行存储。

2.1.1 全量数据迁移方案

通过定时任务将mysql中爬取或者自建的文章同步到HBASE中,并将同步过的数据状态改为已同步,下次同步的时候就不会再次同步这些数据了。

2.1.2 热数据迁移方案

HBASE中有全量数据,大数据端计算出热点数据,需要将这些热点数据同步到MYSQL和MONGDB中,用于页面显示

image.png

2.2 设计思路

  • 将mysql数据库中的全量数据定时读取出来,将多个对象打包成一个对象,保存到HBASE中,保存成功后更新数据库中的状态改为已同步,下一次就不会同步该条数据了。
  • 使用KAFKA监听热点数据计算结果,接收到热点数据信息后,从HBASE得到打包的数据,并将数据进行拆分,将关系数据保存到mysql中,将具体数据保存到mongodb中。
  • 因为热点数据会失效,定期清除mysql和mongodb中的过期数据

2.3 数据同步注意的问题

  • HBASE数据主要靠rowKey进行查询的,rowKey设计就用mysql中的主键ID作为rowKey,查询的时候直接根据Rowkey获取数据
  • 因为需要同步到HBASE的数据是多个数据表的数据,一条数据由多个对象组成,存储的时候使用列族区分不同的对象,里面存储不同的字段。

3 项目中集成hbase与Mongodb

在leadnews-common 集成:

  • hbase.properties

image.png

  • mongo.properties

image.png

  • pom.xml
<!--mongoDB-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!--HBase-->
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-client</artifactId>
    <version>2.1.5</version>
    <exclusions>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
        <exclusion>
            <artifactId>slf4j-log4j12</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
    </exclusions>
</dependency>

host文件配置:

在服务器host文件中配置域名,根据自己的服务器地址更改

172.16.1.52 javaedge

4 常用组件介绍

4.1 Hbase相关操作

Hbase 操作工具类用于将数据存储到Hbase中,其中有些方法用于存储或删除。

4.1.1 项目导入

导入资料文件夹中的项目leadnews-migration

4.1.2 公共存储类

StorageData

公共存储数据表,由多个StorageEntity组成


StorageData 是最重要的一个存储对象,他是保存一个bean信息的类,负责存储bean信息以及转换和反向转换bean 。


该类用到一个重要的工具类ReflectUtils 反射工具类和DataConvertUtils数据类型转换工具类主要用于日期类型的转换

主要方法
  • 添加StorageEntry方法
public void addStorageEntry(StorageEntry entry)

该方法有几个重载方法,用于向StorageEntry列表中添加StorageEntry对象的


  • 获取该对象对应的Object对象
public Object getObjectValue() 

该方法用于将存储的实体数据转换为Bean的实体,用了ReflectUtils反射工具类进行操作


  • 将Bean 转换为StorageData的存储结构
public static StorageData getStorageData(Object bean) 

该方法用于将不同的bean转换为同一种存储结构进行存储

StorageEntity

公共代码存储的实体

StorageEntry

公共存储对象的一个key-value的字段

4.1.3 Hbase操作相关工具类

(1)HBaseConstants 类

配置类Hbase存储的的表名称

public class HBaseConstants {
    public static final String APARTICLE_QUANTITY_TABLE_NAME = "APARTICLE_QUANTITY_TABLE_NAME";
}

(2)HBaseInvok

hbase的的回调操作类

/**
 * Hbase 的回调类
 * 用于我们操作的时候就行回调
 */
public interface HBaseInvok {
    /**
     * 回调方法
     */
    public void invok();
}

(3)HBaseStorage


hbase 的存储对象 继承自StorageEntity


(4)HBaseClent


hbase client操作的工具类


(5)HBaseConfig


用于将HbaseClient对象的相关配置


(6)HBaseStorageClient


Hbase 存储客户端工具类 是对HbaseClient工具类的封装


这个类是自己封装的存储客户端


该类位于heima-leadnews-common 包下的com.heima.hbase.HBaseStorageClient

其中用到了HBaseClent 客户端工具,他是一个操作工具类,不需要我们具体的写拿过来用就可以

4.1.4 测试代码

@SpringBootTest
@RunWith(SpringRunner.class)
public class HbaseTest {
    @Autowired
    private HBaseClent hBaseClent;
    @Test
    public void testCreateTable(){
        List<String> columnFamily = new ArrayList<>();
        columnFamily.add("test_cloumn_family1");
        columnFamily.add("test_cloumn_family2");
        boolean ret = hBaseClent.creatTable("hbase_test_table_name", columnFamily);
    }
    @Test
    public void testDelTable(){
        hBaseClent.deleteTable("hbase_test_table_name");
    }
    @Test
    public void testSaveData(){
        String []columns ={"name","age"};
        String [] values = {"zhangsan","28"};
        hBaseClent.putData("hbase_test_table_name","test_row_key_001","test_cloumn_family1",columns,values);
    }
    @Test
    public void testFindByRowKey(){
        Result hbaseResult = hBaseClent.getHbaseResult("hbase_test_table_name", "test_row_key_001");
        System.out.println(hbaseResult);
    }
}

4.2 MongoDB操作工具类

mongoDB是一个文档型数据库,也需要存储多个不同的对象,我们也用到了HBASE中用到的StorageEntity 存储结构,我们下面会讲

我们用到了Spring MongoTemplate 来操作数据库

介绍以下我们的实体


(1)MongoConstant


mongoDB操作的常量定义了操作mongodb的表名称


代码位置:com.heima.common.mongo.constants.MongoConstant


/

public class MongoConstant {
    public static final String APARTICLE_MIGRATION_TABLE = "APARTICLE_MIGRATION_TABLE";
}

(2)MongoStorageEntity


MongoStorageEntity 是我们存储MongoDB数据的存储结构主要是基于StorageEntity 结构来的


mongoDB操作的实体类继承了StorageEntity 制定了 表明以及实体类型


代码位置:com.heima.common.mongo.entity.MongoStorageEntity


/

/**
 * mongoDB 存储实体
 * Document 是指表明是什么
 */
@Document(collection = "mongo_storage_data")
@Setter
@Getter
public class MongoStorageEntity extends StorageEntity {
    /**
     * 主键的Key
     *
     * @Id 标明该字段是主键
     */
    @Id
    private String rowKey;
}

(3)MongoDBconfigure

对mongdb操作的配置类

代码位置:com.heima.common.mongo.MongoDBconfigure

@Configuration
@PropertySource("classpath:mongo.properties")
public class MongoDBconfigure {
    @Value("${mongo.host}")
    private String host;
    @Value("${mongo.port}")
    private int port;
    @Value("${mongo.dbname}")
    private String dbName;
    @Bean
    public MongoTemplate getMongoTemplate() {
        return new MongoTemplate(getSimpleMongoDbFactory());
    }
    public SimpleMongoDbFactory getSimpleMongoDbFactory() {
        return new SimpleMongoDbFactory(new MongoClient(host, port), dbName);
    }
}

(4)测试代码

@SpringBootTest(classes = MigrationApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MongoTest {
    @Autowired
    private MongoTemplate mongotemplate;
    @Autowired
    private HBaseStorageClient hBaseStorageClient;
    @Test
    public void test() {
        Class<?>[] classes = new Class<?>[]{ApArticle.class, ApArticleContent.class, ApAuthor.class};
        //List<Object> entityList = hBaseStorageClient.getHbaseDataEntityList(HBaseConstants.APARTICLE_QUANTITY_TABLE_NAME, "1", Arrays.asList(classes));
        List<String> strList = Arrays.asList(classes).stream().map(x -> x.getName()).collect(Collectors.toList());
        List<StorageData> storageDataList = hBaseStorageClient.gethBaseClent().getStorageDataList(HBaseConstants.APARTICLE_QUANTITY_TABLE_NAME, "1", strList);
        MongoStorageEntity mongoStorageEntity = new MongoStorageEntity();
        mongoStorageEntity.setDataList(storageDataList);
        mongoStorageEntity.setRowKey("1");
        MongoStorageEntity tmp = mongotemplate.findById("1", MongoStorageEntity.class);
        if (null != tmp) {
            mongotemplate.remove(tmp);
        }
        MongoStorageEntity tq = mongotemplate.insert(mongoStorageEntity);
        System.out.println(tq);
    }
    @Test
    public void test1() {
        MongoStorageEntity mongoStorageEntity = mongotemplate.findById("1", MongoStorageEntity.class);
        if (null != mongoStorageEntity && null != mongoStorageEntity.getDataList()) {
            mongoStorageEntity.getDataList().forEach(x -> {
                System.out.println(x.getObjectValue());
            });
        }
    }
}
相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
运维 Oracle 关系型数据库
免费下载! 《OceanBase 社区版入门到实战》 快人一步,成为游刃有余的分布式数据库专家!
原生分布式关系型数据库OceanBase ,具备多租户、高可用、水平扩展、高性能、低成本、兼容 ORACLE 和 MySQL 六大特点,支撑了支付宝和网商银行全部的核心业务,以及外部银行、保险、证券、运营商、央企等多个行业数百家客户的核心业务系统。OceanBase 在 2021年6月份发布了社区版 3.1,更全面有力的推动数据库生态系统建设。
104308 1
免费下载! 《OceanBase 社区版入门到实战》 快人一步,成为游刃有余的分布式数据库专家!
|
弹性计算 资源调度 负载均衡
OBCP第一章:OB分布式架构高级技术
OBCP第一章:OB分布式架构高级技术
195 0
|
缓存 监控 供应链
36【学习心得】学习心得-数据同步
【学习心得】学习心得-数据同步
36【学习心得】学习心得-数据同步
|
存储 分布式数据库 Hbase
【大厂技术内幕】字节跳动原来是这么做数据迁移的!(中)
【大厂技术内幕】字节跳动原来是这么做数据迁移的!
176 0
【大厂技术内幕】字节跳动原来是这么做数据迁移的!(中)
|
SQL 存储 运维
开源实践 | 携程在 OceanBase 的探索与实践
本文内容主要分享携程在 OceanBase 社区版的探索,将从以下三个方面展开分析:OceanBase 自动化部署、MySQL 实例迁移 OceanBase 以及 OceanBase 方案收益。
339 0
开源实践 | 携程在 OceanBase 的探索与实践
|
存储 Cloud Native NoSQL
一文详解PolarDB披荆斩棘的“秘密武器”
PolarDB由阿里巴巴自主研发的下一代关系型分布式云原生数据库。在兼容传统数据库生态的同时,突破了传统单机硬件的限制,为用户提供大容量,高性能,极致弹性的数据库服务。
694 0
一文详解PolarDB披荆斩棘的“秘密武器”
|
存储 机器学习/深度学习 cobar
|
Cloud Native 数据库 C++
Meetup 报名 | 从数据库到架构,OceanBase CTO 杨传辉邀你聊透分布式
6 月 19 日(本周六),北京 Meetup 开始报名啦!从数据库到架构,我们来聊透分布式
Meetup 报名 | 从数据库到架构,OceanBase CTO 杨传辉邀你聊透分布式
|
关系型数据库 MySQL 分布式数据库
【大厂技术内幕】字节跳动原来是这么做数据迁移的!(下)
【大厂技术内幕】字节跳动原来是这么做数据迁移的!
207 0
|
atlas 数据库 SQL
数据库中间件Atlas调研笔记
13年底的调研笔记,文中的“画外音”是我当时的批注,希望能让大家对Atlas能有一个初步的认识,有疑问之处,欢迎交流。
1135 5