您当前的位置:首页 > 电脑百科 > 程序开发 > 架构

Spring Boot业务系统如何实现海量数据高效实时搜索

时间:2023-09-01 12:39:29  来源:微信公众号  作者:Shepherd

1.概述

我们都知道随着业务系统的发展和使用,数据库存储的业务数据量会越来越大,逐渐成为了业务系统的瓶颈。在阿里巴巴开发手册中也建议:单表行数超过500万行或者单表容量超过2GB才推荐进行分库分表,如果预计三年后数据量根本达不到这个级别,请不要在创建表时就分库分表。数据库最终都是存储在磁盘上,随着数据量变大,会导致数据操作变得缓慢,无论是计算还是IO,但是话又说回来,单表数据量大就一定要进行分库分表操作吗?答案是否定的,因为分库分表本身是一个“很重”的操作,这里就不卖关子了,直接来看看分库分表带来的以下问题和挑战:

  • 重构适配系统  本身我们的业务系统不可能一开始开发上线的时候就会分库分表,都是随着系统使用和时间推移数据量日益膨胀才考虑的,进行分库分表我们业务服务项目代码需要从单一数据库表适配成多库多表,这是一次极其繁重的重构任务,还涉及到数据迁移、备份、扩容等操作问题,该任务上线链路之长、风险之大不言而喻,这也是很多小公司即使数据量上来了也不会马上分库分表的原因吧。
  • 事务问题  目前数据库只能够实现本地事务,也就是在同一个数据库中,可以允许一组操作要么全都正确执行,要么都不执行,从而确保数据库的一致性。单从分区角度出发,实际上仍然是一张表,一个库中,它不会存在事务一致性的问题,但是会使得事务变得非常复杂。而分库分表会涉及到分布式事务,目前数据库并不支持跨库事务,所以在这一块需要解决分布式事务可能带来的不一致性
  • 分页、排序、聚合函数问题   分页需要按照执行的字段进行排序,当排序字段就是分片字段的时候,通过分片规则就比较容易定位到指定的分片;当排序字段并非分片字段的时候,就需要在不同分区、分表中进行排序并且返回,然后再将不同分区、分表中返回的结果集进行汇总和再次排序,最终得到返回结果。取得页数越多,性能受影响也就越大。因为在分区、分表的时候都已经限定了分片字段,而其他字段是跟着分片的字段被分到不同的区域或者表中,这样各个分区、分表中的数据可能是随机的,为了排序的准确性,需要将所有分区、分表节点的前的数据都排好序做合并,最后进行整体排序,这样的操作是非常耗费CPU和内存资源的,所以在分区、分表的情况下、分页数越大,系统的性能也会越差。同样、在使用聚合函数,如Max、Min、Sum、Count进行计算的时候,也会像排序那样在每个分区、分表执行相应的函数,然后再将各个分区、分表的结果集进行汇总和再次计算,最终将结果返回。
  • 全局主键避免重复  单表主键id自增能够保证id不重复,但是分库分表之后,多张表就不能保证主键id不重复了,这时候就要使用分布式id算法进行生成。
  • 数据迁移、扩容问题  随着数据持续增加分表后还需要进行动态新增表时,这个时候就要考虑数据迁移以及扩容问题。一般做法是先读出历史数据,然后按照指定的分表规则再将数据写入各个分表中。这本身就是繁杂之事。

当然以上问题并不是说分库分表是一个不可取的方案,现在分库分表方案在很多公司系统都有应用的,这里想表达的是需要根据个人公司业务系统数据特点,综合评估做权衡来选择解决数据量大的实施方案。

项目推荐:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企业级系统架构底层框架封装,解决业务开发时常见的非功能性需求,防止重复造轮子,方便业务快速开发和企业技术栈框架统一管理。引入组件化的思想实现高内聚低耦合并且高度可配置化,做到可插拔。严格控制包依赖和统一版本管理,做到最少化依赖。注重代码规范和注释,非常适合个人学习和企业使用

Github地址:https://github.com/plasticene/plasticene-boot-starter-parent

Gitee地址:https://gitee.com/plasticene3/plasticene-boot-starter-parent

微信公众号:Shepherd进阶笔记

交流探讨qun:Shepherd_126

2.业务数据量大的解决方案

2.1 数据归档

来分析一个美团业务场景:我们日常每天点外卖,平时会去查看一年前的订单,看看一年前吃了什么吗?答案是几乎不会,或者说这种查询的请求量比较小,出现这种请求大概是有人问你很早之前点的那家外卖好吃,但是你不喜欢记不得了,你帮她查找一下的场景吧~~。由此可见,我们可以根据这一特点进行数据历史归档,即数据做冷、热区分存储。当然这个区分时限要根据自身系统数据特点来指定时限是一年还是半年....这样就能保证我们高频查询的热数据量不大了。

在查询历史数据表时,可以限制查询条件如必须选择日期范围,日期范围不能超过N个月等等从而减轻查询压力。处理历史存量数据比较简单,因为历史数据一般不会变更了,所以一般只需要两个步骤进行归档:

  • 迁移满足限定数据到指定历史归档表
  • 根据主键分批删除业务原表数据,从而降低业务数据量

这里需要强调一下,不能一次性删除所有数据,因为数据量太大可能会引发超时,锁表,长事务等问题,而是应该根据ID分批删除,例如每次删除500或1000条数据。操作步骤如下:

SELECT MAX(id) AS maxId FROM t WHERE create_time < '指定时间'

查出满足归档条件的数据最大id,接下来就可以分批归档和删除了,初始化 startId=0,每次归档500条

select * into t_bak from t where id > startId and id <= maxId limit 500

查询归档表获取最大id:maxBakId,赋值给startId方便下次分批归档删除

select max(id) from t_bak

数据删除:

delete from t where id <= maxBakId

重复上面的归档删除操作,直至startId到maxId结束

2.2 读写分离和热点缓存

大部分的业务系统场景都是读多写少,读写比一般都在几十左右,平均每发生几十次查询请求,才有一次更新请求。换句话来说,数据库需要应对的绝大部分请求都是只读查询请求。针对这种情况我们可以通过读写分离方案来降低数据库压力。

图片图片

主库负责执行应用程序发来的所有数据更新请求,然后异步将数据变更实时同步到所有的从库中去,这样,主库和所有从库中的数据是完全一样的。多个从库共同分担应用的查询请求。

对于一些高频访问的热点数据,我们可以提前预处理使用redis缓存,这样也可以有效降低数据库的压力。

2.3 同步异构数据源

我们知道MySQL会随着数据量增大而查询变慢,那么我们换成其他数据源来完成OLAP查询场景不就得了。特别是在当下大数据时代,现在互联网公司一般都具备与之规模相对应的大数据服务或者平台,那么作为业务开发者要善于应用公司大数据能力,减轻业务数据库压力。比如我们可以把数据同步到ES、HBASE等平台。

使用elasticsearch来实现海量数据搜索就是一个不错的选择,elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用JAVA开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。能够达到实时搜索,稳定,可靠,快速,安装使用方便。但是如何实现MySQL数据同步elasticsearch呢?

答案是阿里的开源项目Canal,就是用来解决异构数据源数据同步这个问题的,Canal项目利用了MySQL数据库主从同步的原理,将Canal Server模拟成一台需要同步的从库,从而让主库将binlog日志流发送到Canal Server接口。Canal项目对binlog日志的解析进行了封装,我们可以直接得到解析后的数据,而不需要理会binlog的日志格式。而且Canal项目整合了zookeeper,整体实现了高可用,可伸缩性强

图片图片

2.4 分库分表

如果通过以上:历史数据归档、数据同步异构数据源、读写分离、热点缓存都不能解决MySQL单表数据压力的,这时我们只能拆分数据表,即把单库单表数据迁移到多库多表中。这也是一线流量互联网公司需要面对的,你试想一下淘宝双11那几天要上架多少商品,产生多少订单,这已经不是前面的方案所能解决了,只能分库分表了。当然分库分表是一个复杂的操作,也不是三言两语就能全面讲清楚的,且也不是我们今天主要议题,所以我这里粗略概述一下,感兴趣的可自行查阅相关资料。

垂直拆分

垂直拆分就是按照业务拆分,我们将电商数据库拆分成三个库,订单库、商品库。支付库,订单表在订单库,商品表在商品库,支付表在支付库。这样每个库只需要存储本业务数据,物理隔离不会互相影响。

水平拆分

按照垂直拆分方案,现在我们已经有三个库了,平稳运行了一段时间。但是随着业务增长,每个单库单表的数据量也越来越大,逐渐到达瓶颈。

这时我们就要对数据表进行水平拆分,所谓水平拆分就是根据某种规则将单库单表数据分散到多库多表,从而减小单库单表的压力。

水平拆分策略有很多方案,最重要的一点是选好ShardingKey,也就是按照哪一列进行拆分,怎么分取决于我们访问数据的方式。

比如我们可以根据时间范围分片,根据创建时间分配到不同的表中。也可以根据哈希分表,哈希分片可以较为均匀将数据分散在数据库中。我们现在将订单库拆分为4个库编号为[0,3],每个库4张表编号为[0,3],根据分布式id%编号落库,当然也有其他分片方案,这取决于你们公司业务数据特点。

3.如何实时同步数据到elasticsearch支持海量查询

我一开始就强调了分库分表带来的问题,可见今天的重点肯定不是采用分库分表来解决数据量大的问题的,所以我接下来来讲讲我司的解决方案:数据归档+读写分离+同步异构数据源

数据归档可以有效降低数据库数据量,读写分离可以降低单数据库的读写压力,异构数据源es满足日常查询性能要求。

数据归档的操作步骤前面说过了,至于数据库读写分离实现方案等后续有时间再分析一波,今天主要讲讲如何高效实时同步elasticsearch满足查询要求。直接看架构图:

图片图片

数据同步elasticsearch大概有两种:

1.针对代码中进行数据库的增删改操作时,同时进行elasticsearch的增删改操作。这种方式代码侵入性强,耦合度高,实时性高,改造起来比较痛苦,因为你不能错过任何一个增删改的地方同步操作es,否则就会出现数据不一致问题。

2.利用监听mysql binlog同步,实时性强,对于应用无任何侵入性,且性能更好,不会造成资源浪费。正好阿里巴巴开源的canal就是干这个的,完美解决问题。通过上面的架构图知道可以通过canal client拿到canal server对binlog的解析直接同步到es,但是这种方式处理比较慢,等于我们是一条一条的去同步,很多情况下es的索引表是一张大宽表,是来自MySQL几张表join的信息,这要求我们同步的时候还要根据主键通过join sql语句查出数据再同步,自然就更慢了。所以要使用消息队列kafka进行数据削峰填谷,批量操作是保证实时性的关键。

4.总结

以上全部就是我们对海量数据实时搜索的解决方案浅析,各有利弊。我们可以根据自身的业务数据情况选择合适的方案即可,切勿动不动就来分库分表,显得有点不知深浅。

本文转载自微信公众号「Shepherd进阶笔记」



Tags:Spring Boot   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Spring Boot2.0深度实践 核心原理拆解+源码分析
Spring Boot2.0深度实践:核心原理拆解与源码分析一、引言Spring Boot是一个基于Java的轻量级框架,它简化了Spring应用程序的创建过程,使得开发者能够快速搭建一个可运行的应用...【详细内容】
2024-01-15  Search: Spring Boot  点击:(93)  评论:(0)  加入收藏
Spring Boot 3.0是什么?
Spring Boot 3.0是一款基于Java的开源框架,用于简化Spring应用程序的构建和开发过程。与之前的版本相比,Spring Boot 3.0在多个方面进行了改进和增强,使其更加易用、高效和灵活...【详细内容】
2024-01-11  Search: Spring Boot  点击:(132)  评论:(0)  加入收藏
GraalVM与Spring Boot 3.0:加速应用性能的完美融合
在2023年,SpringBoot3.0的发布标志着Spring框架对GraalVM的全面支持,这一支持是对Spring技术栈的重要补充。GraalVM是一个高性能的多语言虚拟机,它提供了Ahead-of-Time(AOT)编...【详细内容】
2024-01-11  Search: Spring Boot  点击:(124)  评论:(0)  加入收藏
Spring Boot虚拟线程的性能还不如Webflux?
早上看到一篇关于Spring Boot虚拟线程和Webflux性能对比的文章,觉得还不错。内容较长,抓重点给大家介绍一下这篇文章的核心内容,方便大家快速阅读。测试场景作者采用了一个尽可...【详细内容】
2024-01-10  Search: Spring Boot  点击:(115)  评论:(0)  加入收藏
Spring Boot Starter的原理
Spring Boot Starter 是 Spring Boot 框架的特性之一,用于简化应用程序的依赖管理和配置。1. 概述: - Spring Boot Starter 是一种包含了一组特定功能和依赖关系的依赖项,旨在...【详细内容】
2024-01-05  Search: Spring Boot  点击:(93)  评论:(0)  加入收藏
Spring Boot 统一响应体处理器详解
在Spring Boot应用中,统一处理响应体是一项非常重要的任务,它可以让我们更方便地统一规范API的返回格式。今天,我们将深入探讨一个优雅的解决方案&mdash;&mdash;使用ResultHand...【详细内容】
2023-11-30  Search: Spring Boot  点击:(150)  评论:(0)  加入收藏
Spring Boot 调优内嵌 Tomcat 的三种方法
在 Spring Boot 中优化 Apache Tomcat 有三种方式,以便实现更好的性能和资源利用率。 线程池(连接器和执行器)设置 使用 NIO 或 APR 连接器 JVM优化线程池设置在 Spring Boot...【详细内容】
2023-11-23  Search: Spring Boot  点击:(227)  评论:(0)  加入收藏
一文搞懂Spring Boot控制器的关键要点
Spring Boot 应用程序中的控制器扮演着重要角色,负责处理传入的 HTTP 请求并确定应发送的适当响应。本文深入介绍 Spring Boot 中的控制器,包括如何创建控制器、处理各种类型...【详细内容】
2023-11-20  Search: Spring Boot  点击:(151)  评论:(0)  加入收藏
Spring Boot中实现订单30分钟自动取消的策略思路及源代码
方式一:使用定时任务 首先,创建一个定时任务,比如每30分钟执行一次检查订单是否需要取消的逻辑。 在订单生成的时候,保存一条记录到数据库,标记订单的状态为"待处理"。 在定时任...【详细内容】
2023-11-20  Search: Spring Boot  点击:(217)  评论:(0)  加入收藏
Spring Boot + Vue3 前后端分离 实战wiki知识库系统
下栽の地止:https://www.itwangzi.cn/2508.html Spring Boot + Vue3 前后端分离 实战wiki知识库系统在当今的Web应用开发中,前后端分离已经成为了一种主流的开发模式。Spring...【详细内容】
2023-11-18  Search: Spring Boot  点击:(143)  评论:(0)  加入收藏
▌简易百科推荐
对于微服务架构监控应该遵守的原则
随着软件交付方式的变革,微服务架构的兴起使得软件开发变得更加快速和灵活。在这种情况下,监控系统成为了微服务控制系统的核心组成部分。随着软件的复杂性不断增加,了解系统的...【详细内容】
2024-04-03  步步运维步步坑    Tags:架构   点击:(5)  评论:(0)  加入收藏
大模型应用的 10 种架构模式
作者 | 曹洪伟在塑造新领域的过程中,我们往往依赖于一些经过实践验证的策略、方法和模式。这种观念对于软件工程领域的专业人士来说,已经司空见惯,设计模式已成为程序员们的重...【详细内容】
2024-03-27    InfoQ  Tags:架构模式   点击:(13)  评论:(0)  加入收藏
哈啰云原生架构落地实践
一、弹性伸缩技术实践1.全网容器化后一线研发的使用问题全网容器化后一线研发会面临一系列使用问题,包括时机、容量、效率和成本问题,弹性伸缩是云原生容器化后的必然技术选择...【详细内容】
2024-03-27  哈啰技术  微信公众号  Tags:架构   点击:(10)  评论:(0)  加入收藏
DDD 与 CQRS 才是黄金组合
在日常工作中,你是否也遇到过下面几种情况: 使用一个已有接口进行业务开发,上线后出现严重的性能问题,被老板当众质疑:“你为什么不使用缓存接口,这个接口全部走数据库,这怎么能扛...【详细内容】
2024-03-27  dbaplus社群    Tags:DDD   点击:(11)  评论:(0)  加入收藏
高并发架构设计(三大利器:缓存、限流和降级)
软件系统有三个追求:高性能、高并发、高可用,俗称三高。本篇讨论高并发,从高并发是什么到高并发应对的策略、缓存、限流、降级等。引言1.高并发背景互联网行业迅速发展,用户量剧...【详细内容】
2024-03-13    阿里云开发者  Tags:高并发   点击:(6)  评论:(0)  加入收藏
如何判断架构设计的优劣?
架构设计的基本准则是非常重要的,它们指导着我们如何构建可靠、可维护、可测试的系统。下面是这些准则的转换表达方式:简单即美(KISS):KISS原则的核心思想是保持简单。在设计系统...【详细内容】
2024-02-20  二进制跳动  微信公众号  Tags:架构设计   点击:(36)  评论:(0)  加入收藏
详解基于SpringBoot的WebSocket应用开发
在现代Web应用中,实时交互和数据推送的需求日益增长。WebSocket协议作为一种全双工通信协议,允许服务端与客户端之间建立持久性的连接,实现实时、双向的数据传输,极大地提升了用...【详细内容】
2024-01-30  ijunfu  今日头条  Tags:SpringBoot   点击:(10)  评论:(0)  加入收藏
PHP+Go 开发仿简书,实战高并发高可用微服务架构
来百度APP畅享高清图片//下栽のke:chaoxingit.com/2105/PHP和Go语言结合,可以开发出高效且稳定的仿简书应用。在实现高并发和高可用微服务架构时,我们可以采用一些关键技术。首...【详细内容】
2024-01-14  547蓝色星球    Tags:架构   点击:(115)  评论:(0)  加入收藏
GraalVM与Spring Boot 3.0:加速应用性能的完美融合
在2023年,SpringBoot3.0的发布标志着Spring框架对GraalVM的全面支持,这一支持是对Spring技术栈的重要补充。GraalVM是一个高性能的多语言虚拟机,它提供了Ahead-of-Time(AOT)编...【详细内容】
2024-01-11    王建立  Tags:Spring Boot   点击:(124)  评论:(0)  加入收藏
Spring Boot虚拟线程的性能还不如Webflux?
早上看到一篇关于Spring Boot虚拟线程和Webflux性能对比的文章,觉得还不错。内容较长,抓重点给大家介绍一下这篇文章的核心内容,方便大家快速阅读。测试场景作者采用了一个尽可...【详细内容】
2024-01-10  互联网架构小马哥    Tags:Spring Boot   点击:(115)  评论:(0)  加入收藏
站内最新
站内热门
站内头条