【解决方案】项目重构之如何使用 MySQL 替换原来的 MongoDB

news/2024/10/1 23:42:20

目录
  • 前言
  • 一、痛点所在
  • 二、选型分析
    • 2.1特点对比
    • 2.2场景对比
  • 三、核心思路
  • 四、demo 示例
    • 4.1实体映射
      • 4.1.1MongoDB 实体
      • 4.1.2MySQL 实体
    • 4.2查询代码
      • 4.2.1MongoDB 查询
      • 4.2.2MySQL 查询
  • 五、文章小结

前言

在笔者 Java 后端开发的项目经历中,MySQL 和 MongoDB 都有使用过作为后端的数据库来对业务数据进行持久化,两者没有孰优孰劣之分,都可以在合适的场景下发挥出它们的优势。

今天要分享的是一个项目重构过程中如何将数据库选型由原来的 MongoDB 改为 MySQL 的思考,涉及到业务当前的痛点、选型分析、解决的核心思路,最后会给出简单的 demo。

本篇文章侧重在于两者在表设计思维上的转换,而业务数据迁移同步的方案,下一篇文章将给出。


一、痛点所在

该项目是一个【PC端管理后台】+【移动端h5页面】为主业务框架的系统,原来的预期是:在后台配置好活动所需的参数,h5 既可以放在 app 客户端打开,也可以作为url 链接的形式直接在浏览器打开。项目一期的时候,业务方认为这样的运营活动会带来不少的流量和用户。但是到后来业务重心有所调整,引流的方式发生变化,最终导致了项目的一个重构。

主要的原因有以下几点:

  1. 总体的数据量没有预想的那么大

    活动参与人数前期预估为30w+,经历过2个线上活动后的实际总参与人数为5w+,客户端注册用户数为3w+,占全部参与人数的65%左右,远不及预期规模;

  2. 核心接口的并发也没有预想的高

    h5 端的大约 5-8 个的核心接口在实际线上活动进行的最高 QPS 只达到 200-300 左右,CPU 与 内存占用率也未达到设置的告警线(60%);

  3. MySQL 在硬件资源成本上性价比更高

    以阿里云的 RDS for MySQL 与 云数据库 MongoDB 做对比,都是集群部署 + 8核16GB + 100GB 存储 + 1年时长的规格下,前者会比后者便宜7w+RMB;

  4. MySQL 的动态数据源切换方案更成熟

    当时后端的项目已经被全部要求接入多租户改造,市面上开源的、成熟的动态数据源切换方案并不多,而完全专门支持 MongoDB 的是少之又少。

综合以上几点原因,完全放弃该项目是没必要的,但也需要适应当前业务的变化和成本控制,预计花费30人/天,即 2 个后端开发在 2-3 周内完成对该系统的重构,接口和前端页面基本无需调整。


二、选型分析

这里就正式进入技术部分了,首要对比的是两者各自的特点以及适用的场景,这对于把握整个项目的走向是至为关键的。

2.1特点对比

表2-1
对比项 MySQL MongoDB
数据模型 关系型数据库,采用表格(table)的形式存储数据,每一行是一条记录 非关系型(NoSQL)、文档型数据库,数据以文档(document)的非结构化形式存储
查询方式 使用标准的 SQL 进行查询,提供了丰富的查询条件、连接(join)、排序、分页等功能 使用基于 JSON 结构特点的的查询语句,支持大量数据的聚合、统计、分析
事务支持 支持 ACID 事务,确保在多条操作组成的事务中数据的一致性和可靠性。特别是在InnoDB引擎中,提供了完整的事务支持 4.0 版本开始引入了多文档事务支持,可以保证在一定范围内的读写操作具备ACID特性。但对于需要严格事务特性的复杂业务场景不及 MySQL 成熟
数据处理 在处理复杂查询和高并发写入时,需要依赖索引来优化性能,或者通过分区、分片等手段进行水平扩展 在水平扩展和实时数据处理方面优势很大,通过分片(sharding)技术可以轻松应对海量数据存储和高并发读写
空间占用 由于数据结构紧凑,对数据的存储通常更为节省空间,特别是对于简单数据结构和关系清晰的数据集 由于文档存储的灵活性和包含元数据等因素,通常占用空间较大
项目集成 已经有成熟的第三方 ORM 框架支持,如:Mybatis、Mybatis Plus、io.mybatis、tk.mybatis等 目前集成在 Spring Boot 项目里的增删改查都是基于 MongoRepository 和 MongoTemplate 来实现的

2.2场景对比

  • MySQL
    1. Web 应用程序:如常见的 xx 管理后台、xx 管理系统,电商 web 网站,包括一些移动端 h5 的页面等;
    2. 企业级应用:如常见的客户关系管理系统(CRM)、人力资源管理系统(HRM)和供应链管理系统(SCM)等,MySQL 提供了强大的事务支持;
    3. 嵌入式开发:需要轻量级数据库的软件、硬件和设备,MySQL 可以作为一个嵌入式数据库引擎集成到各种应用程序中,提高应用程序的可移植性;
    4. 云计算和大数据:MySQL 在云数据库服务中被广泛使用,支持云原生应用程序和分布式数据处理框架,如 Hadoop 和 Spark 等。
  • MongoDB
    1. 处理实时数据:非常适合处理移动互联网应用常见的大部分场景,如用户活动、社交互动、在线购物等;
    2. 内容管理系统(CMS):用于处理文章、稿件、评论、图片、视频等富媒体内容的存储和增删改查,支持全文搜索和实时更新;
    3. 数据聚合仓库:存储原始或半处理的业务数据,利用聚合框架进行实时数据聚合、统计分析和数据可视化;
    4. 游戏数据管理:存储玩家账户信息、游戏进度、成就、虚拟物品、社交关系等,快速计算和更新游戏排行榜数据,支持实时查询等。

三、核心思路

我们知道,在 MongoDB 中,一条数据的记录(文档)格式是 json 的 格式,即强调 key-value 的关系。

表2-2

对于一个 MongoDB 的文档来说,里面可以包含很多这个集合的属性,就像一篇文章里面有很多章节一样。

以下面这个图2-1为例子,activity 是一个完整的集合,里面包含了很多属性,id、name、status等基本属性,还有 button 和 share 等额外属性,这些属性共同构成了这个集合。

但这样的结构在 MySQL 里是不能实现的,理由很简单,MySQL 强调关系,1:1 和 1:N 是十分常见的关系。可以看到,下面将基本属性放在 activity 作为主表,而其它额外属性分别放在了 button 表和 share 表里,同时将主表的主键 id 作为了关联表的 ac_id 外键。

图2-1

那要怎么替换才能实现呢?MongoDB 改成 MySQL 的核心在于:原有的集合关系以及嵌套关系,需要拆表成1 : N 的范式关系,用主键-外键的方式做关联查询,同时避免 join 连接查询。


四、demo 示例

下面首先分别给出实际的表设计与实体映射,包括 MongoDB 和 MySQL 的,然后再通过简单的查询代码来体现两者的区别。

4.1实体映射

4.1.1MongoDB 实体
@EqualsAndHashCode(callSuper = true)
@Data
public class Activity extends BaseEntity {@Idprivate String id;private String name;private ActivityStatusEnum status;private ReviewStatusEnum review;private ActivityTypeEnum type;private ActivityButton button;private ActivityShare share;
}
4.1.2MySQL 实体
@Data
public class Activity extends BaseEntity {@Idprivate Integer id;private String name;private Integer status;private Integer review;private Integer type;
}
@Data
public class ActivityButton extends BaseEntity {@Idprivate Integer id;private Integer acId;private String signUp;private Integer status;private String desc;
}
@Data
public class ActivityShare extends BaseEntity {@Idprivate String id;private Integer acId;private String title;private String iconUrl;
}

4.2查询代码

下面就根据主键 id 和状态这两个条件进行活动详情的查询。

4.2.1MongoDB 查询
    /*** @apiNote 通过主键id和活动状态查询活动* @param id 主键id* @return 实体*/@Overridepublic Avtivity getDetailById(String id) {return this.repository.findById(id).filter(val -> ActivityStatusEnum.ON.equals(val.getStatus())).orElseThrow(() -> new RuntimeException("该活动不存在!"));}
4.2.2MySQL 查询
    @Resourceprivate ActivityShareService activityShareService;@Resourceprivate ActivityButtonService activityButtonService;@Overridepublic ActivityVO detail(Integer id) {ExampleWrapper<Activity, Serializable> wrapper = this.wrapper();wrapper.eq(Activity::getid, id).eq(Activity::getStatus(), DataStatusEnum.NORMAL.getCode());Activity activity = Optional.ofNullable(this.findOne(wrapper.example())).orElseThrow(() -> new RuntimeException("该活动不存在!"));ActivityVO vo = new ActivityVO();vo.setName(Optional.ofNullable(activity.getName()).orElse(StringUtils.EMPTY));//查两个关联表vo.setShare(this.activityShareService.getShare(activity.getId()));vo.setButton(this.activityButtonService.getButton(activity.getId()));return vo;}

五、文章小结

使用 MySQL 替换 MongoDB 的小结如下:

  1. 做技术选型时要充分考虑对比两者的特点以及应用场景,选择最合适的
  2. 如非必要,那么还是继续沿用原来的设计;一旦选择重构,那么就要考虑成本
  3. 原有的集合关系以及嵌套关系,需要拆表成1 : N 的范式关系,用主键-外键的方式做关联

最后,如有不足和错误,还请大家指正。或者你有其它想说的,也欢迎大家在评论区交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/55558.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Windows Server 2022 OVF, updated Aug 2024 (sysin) - VMware 虚拟机模板

Windows Server 2022 OVF, updated Aug 2024 (sysin) - VMware 虚拟机模板Windows Server 2022 OVF, updated Aug 2024 (sysin) - VMware 虚拟机模板 2024 年 8 月版本更新,现在自动运行 sysprep,支持 ESXi Host Client 部署 请访问原文链接:https://sysin.org/blog/windows…

金九银十来了,你的简历写好了么?

大家好,我是晓凡。 写在前面 时间过得真快,转眼间就来到了九月份。都说金九银十,又到了一年一度的求职跳槽黄金季。 这两年就业环境应该不用我多说了吧,只能用一个惨字来形容。 即使就业环境再怎么不堪,但毕业了工作总要找的,总不可能啃老摆烂吧。 在这竞争激烈的时期,一…

UTM v4.5.4 - 在 macOS 上优雅的使用 QEMU 虚拟化 Windows、Linux 和 macOS

UTM v4.5.4 - 在 macOS 上优雅的使用 QEMU 虚拟化 Windows、Linux 和 macOSUTM v4.5.4 - 在 macOS 上优雅的使用 QEMU 虚拟化 Windows、Linux 和 macOS 在 iPhone 和 iPad 中虚拟化 Windows、Linux 和 Unix,如此简单! 请访问原文链接:https://sysin.org/blog/utm-4/,查看最…

Burp Suite Professional 2024.8 for macOS x64 ARM64 - 领先的 Web 渗透测试软件

Burp Suite Professional 2024.8 for macOS x64 & ARM64 - 领先的 Web 渗透测试软件Burp Suite Professional 2024.8 for macOS x64 & ARM64 - 领先的 Web 渗透测试软件 世界排名第一的 Web 渗透测试工具包 请访问原文链接:https://sysin.org/blog/burp-suite-pro-mac…

VMware Fusion 13.5.2 更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware Fusion 13.5.2 更新 OEM BIOS 2.7 支持 Windows Server 2025VMware Fusion 13.5.2 更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware Fusion 13.5.2 OEM BIOS 2.7 - 在 macOS 中运行 Windows 虚拟机的最佳方式 VMware Fusion 13 原版 App 中集成 OEM BIOS 请访问原文…

VMware Workstation 17.5.2 Pro macOS Unlocker 更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware Workstation 17.5.2 Pro macOS Unlocker 更新 OEM BIOS 2.7 支持 Windows Server 2025VMware Workstation 17.5.2 Pro macOS Unlocker 更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware Workstation 17.5.2 Pro Unlocker & OEM BIOS 2.7 for Windows & Linux…

VMware ESXi 8.0U3 macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware ESXi 8.0U3 macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025VMware ESXi 8.0U3 macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成驱动…

VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025VMware ESXi 7.0U3q macOS Unlocker 集成驱动版更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware ESXi 7.0U3q macOS Unlocker & OEM BIOS 2.7 集成网卡驱动和 NVMe 驱动 (集成…