企业网站建设费用 珠海,品牌建设和品牌打造方法,中信建设有限责任公司企业邮箱,网站建设计入什么费用1.概述
我们都知道随着业务系统的发展和使用#xff0c;数据库存储的业务数据量会越来越大#xff0c;逐渐成为了业务系统的瓶颈。在阿里巴巴开发手册中也建议#xff1a;单表行数超过500万行或者单表容量超过2GB才推荐进行分库分表#xff0c;如果预计三年后数据量根本达…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进阶笔记 交流探讨qunShepherd_126 2.业务数据量大的解决方案
2.1 数据归档
来分析一个美团业务场景我们日常每天点外卖平时会去查看一年前的订单看看一年前吃了什么吗答案是几乎不会或者说这种查询的请求量比较小出现这种请求大概是有人问你很早之前点的那家外卖好吃但是你不喜欢记不得了你帮她查找一下的场景吧~~。由此可见我们可以根据这一特点进行数据历史归档即数据做冷、热区分存储。当然这个区分时限要根据自身系统数据特点来指定时限是一年还是半年…这样就能保证我们高频查询的热数据量不大了。
在查询历史数据表时可以限制查询条件如必须选择日期范围日期范围不能超过N个月等等从而减轻查询压力。处理历史存量数据比较简单因为历史数据一般不会变更了所以一般只需要两个步骤进行归档
迁移满足限定数据到指定历史归档表根据主键分批删除业务原表数据从而降低业务数据量
这里需要强调一下不能一次性删除所有数据因为数据量太大可能会引发超时锁表长事务等问题而是应该根据ID分批删除例如每次删除500或1000条数据。操作步骤如下
SELECT MAX(id) AS maxId FROM t WHERE create_time 指定时间查出满足归档条件的数据最大id接下来就可以分批归档和删除了初始化 startId0每次归档500条
select * into t_bak from t where id startId and id maxId limit 500查询归档表获取最大idmaxBakId赋值给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.总结
以上全部就是我们对海量数据实时搜索的解决方案浅析各有利弊。我们可以根据自身的业务数据情况选择合适的方案即可切勿动不动就来分库分表显得有点不知深浅。