分表后需要注意的二三事

5d012e6a6fd7729354.jpg

前言

本篇是上一篇《一次分表踩坑实践的探讨》,所以还没看过的朋友建议先看上文。

还是先来简单回顾下上次提到了哪些内容:

  • 分表策略:哈希、时间归档等。
  • 分表字段的选择。
  • 数据迁移方案。

而本篇文章的背景是在我们上线这段时间遇到的一些问题并尝试解决的方案。

问题产生

之前提到在分表应用上线前我们需要将原有表的数据迁移到新表中,这样才能保证业务不受影响。

5d0126128f1e678414.jpg

所以我们单独写了一个迁移应用,它负责将大表中的数据迁移到 64 张分表,而再迁移过程中产生的数据毕竟是少数,最后在上线当晚再次迁移过去即可。

一切想的很美好,当这个应用上线后却发现没这么简单。

数据库负载升高

首先第一个问题是数据库自己就顶不住了,在我们上这个迁移程序之前数据库的压力本身就比较大,这个应用一上去就成了最后一根稻草。

最后导致的结果是:所有连接了数据库的程序大部分的操作都出现超时,获取不到数据库连接等一系列的异常。

最后没办法我们只能把这个应用放到凌晨执行,但其实后面观察发现依然不行。

虽说凌晨的业务量下降,但依然有少部分的请求过来,也会出现各种数据库异常。

再一个是迁移程序的效率也非常低下,按照这样是速度,我们预估了一下迁移时间,大约需要 10 几天才能把三张最大的表(3、4亿的数据)迁移到分表中。

于是我们换了一个方案,将这个迁移程序在从库中运行,最后再用运维的方法将分表直接导入进主库。

因为从库的压力要比主库小很多,对业务的影响很小,同时迁移的效率也要快很多。

即便是这样也花了一晚上+一个白天的时间才将一张 1亿的数据迁移完成,但是业务上的压力越来越大,数据量再不断新增,这个效率依然不够。

兼容方案

最终没办法只有想一个不迁移数据的方案,但是新产生的数据还是往分表里写,至少保证大表的数据不再新增。

但这样对于以前的数据咋办呢?总不能不让看了吧。

其实对于数据的操作无非就分为增删改查,就这四种操作来看看如何兼容。

新增

5d012612de57f13422.jpg

新增最简单,所有的数据根据分表规则直接写入新表,这样可以保证老表的数据不再新增。

删除

删除就要比新增稍微复杂一些,比如用户想要删除他个人产生的一条信息(比如说是订单数据),有可能这个数据在新表也可能在老表。

5d01261336daf24547.jpg

所以删除时优先删除新表(毕竟新产生的数据访问的频次越高),如果删除失败再从老表删除一次。

修改

5d01261380d6599845.jpg

而修改同理,同样的会不确定数据存在于哪里,所以先要修改新表,失败后再次修改老表。

查询

查询相对就要复杂一些了,因为这些大表的数据大部分都是存放一个用户产生的多条记录(比如一个用户的订单信息)。

这时在页面上通常都会有分页,并且按照时间进行排序。

麻烦的地方就出在这里:既然是要分页那就有可能出现要查询一部分分表数据和原来的大表数据做组合。

所以这里的查询其实分为三种情况。

5d012613da28015150.jpg

  • 首先查询的时候要计算这个用户所在分表中的数据可以分为几页。
  • 第一步首先判断当前页是否可以在分表中全部获取,如果可以则直接从分表中取出数据返回(假设分页中总共可以查询 2 页数据,当前为第 1 页,那就全部取分表数据)。
  • 如果不可以就要判断当前页数在分表中是否取不到任何一条数据,如果是则直接取老表数据(比如现在要取第 5 页的数据,分表中一共才只有 2 页数据,所以第 5 页数据只能全部从老表中获取)。
  • 但如果分表和老表都存在一部分数据时,则需要同时取两张表然后做一个汇总再返回。

这种逻辑只适用于根据分表字段进行查询分页的前提下


我想肯定会有朋友提出这样是否会有性能问题?

同时如果在计算分表分页数量时出现并发写入的情况,导致分页数量不准从而对后续的查询出现影响该怎么处理?

首先第一个性能问题:

其实这个要看怎么取舍,为了这样的兼容目的其实会比常规查询多出几个步骤:

  • 判断当前页是否可以在分表中查询。
  • 当新老表中都有数据时候需要额外多查询一张大表。

第一个判断逻辑其实是在内存中计算,这个损耗我觉得完全可以忽略不计。

至于第二步确实会有损耗,毕竟多查了一张表。

但在分表之前所有的数据都是从老表中获取的,当时的业务也没有出现问题;现在多的只是查询分表而已,但分表的数据量肯定要比大表小的多,而且有索引,所以这个效率也不会慢多少。

而且根据局部性原理及用户的使用习惯来看,老表中的数据很少会去查询,随着时间的推移所有的数据肯定都会从分表中获取,逐渐老表就会成为历史表。

而第二个并发带来的问题我觉得影响也不大,一定要这个分页准的前提肯定得是加锁了,但为了这样一个不痒的小问题却带来性能的下降,我觉得是不划算的。

而且后续我们也可以慢慢的将老表的数据迁移到新表,这样就可以完全去掉这个兼容逻辑了,所有的数据都从分表中获取。

总结

还是之前那句话,这里的各种操作、方法不适合所有人,毕竟脱离场景都是耍牛氓。

比如分表搞的早,业务上允许一定的时间将数据迁移到分表那就不会有这次的兼容处理。

甚至一开始业务规划合理、团队架构师看的长远,一来就将关键数据分表存储那根本就不会有数据迁移这个流程(大厂有经验的团队可能,小公司小作坊都得靠自己摸索)。

这段期间也被数据库折腾惨了,数据库是最后一根稻草果然也不是瞎说的。

你的点赞与分享是对我最大的支持

转载于:https://www.cnblogs.com/crossoverJie/p/11013769.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DNS 原理

阮老师的作品,非常精彩,转载! DNS 是互联网核心协议之一。不管是上网浏览,还是编程开发,都需要了解一点它的知识。 本文详细介绍DNS的原理,以及如何运用工具软件观察它的运作。我的目标是,读完此…

leetcode1169. 查询无效交易

如果出现下述两种情况,交易 可能无效: 交易金额超过 1000 或者,它和另一个城市中同名的另一笔交易相隔不超过 60 分钟(包含 60 分钟整) 每个交易字符串 transactions[i] 由一些用逗号分隔的值组成,这些值分…

销售员/学员/讲师系统

前言: 今晚写一篇关于学员/讲师/销售员CRM系统。这个小项目是27号开始做的,大概搞了一星期不到。我把一些知识点总结下,还写下当时克服的BUG。 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣和效率最高的,今天…

Linux内核启动

1 内核编译 解压缩&#xff1a;tar xjf linux-2.6.22.6.tar.bz2打补丁&#xff1a; path -p1 < ../linux-2.6.22.6_jz2440.patch(其中p1是忽略补丁文件中的一级目录)配置&#xff1a; 方法一&#xff1a;使用make menuconfig逐项配置方法二&#xff1a;使用默认配置&#xf…

node.js使用手册_权威的Node.js手册

node.js使用手册Developer and freeCodeCamp camper Flavio Copes has published his entire Node.js Handbook online for free - both on freeCodeCamps Medium publication and as a .pdf file. You can read it here.开发人员和freeCodeCamp营员Flavio Copes在freeCodeCamp…

自动化运维之saltstack(二)states深入理解

深入了解SLS的可以参考这篇博文&#xff1a;http://www.ituring.com.cn/article/42238 个人觉得这篇文章翻译的不错&#xff0c;所以转载过来。 Salt Sates 众多强大而有力的涉及都是建立在简单的原则之上。Salt SLS系统也是努力想K.I.S.S看齐。&#xff08;Keep It Stupidly …

java里面的 |运算符_Java 中 | ^ 运算符的简单使用

背景今天碰到了代码中的按位与运算&#xff0c;复习一下&#xff0c;先列一个各个进制数据表。顺便复习一下十进制转二进制的计算方式&#xff1a;接下来解释下这三个运算符&#xff1a;&  按位与&#xff0c;都转为二进制的情况下&#xff0c;同为1则为1&#xff0c;否则…

leetcode915. 分割数组

给定一个数组 A&#xff0c;将其划分为两个不相交&#xff08;没有公共元素&#xff09;的连续子数组 left 和 right&#xff0c; 使得&#xff1a; left 中的每个元素都小于或等于 right 中的每个元素。 left 和 right 都是非空的。 left 要尽可能小。 在完成这样的分组后返回…

彻底理解正向代理、反向代理、透明代理

套用古龙武侠小说套路来说&#xff0c;代理服务技术是一门很古老的技术&#xff0c;是在互联网早期出现就使用的技术。一般实现代理技术的方式就是在服务器上安装代理服务软件&#xff0c;让其成为一个代理服务器&#xff0c;从而实现代理技术。常用的代理技术分为正向代理、反…

使用showMessageDialog显示消息框

-----------------siwuxie095 工程名&#xff1a;TestJOptionPane 包名&#xff1a;com.siwuxie095.showdialog 类名&#xff1a;TestMessageDialog.java 工程结构目录如下&#xff1a; 代码&#xff1a; package com.siwuxie095.showdialog; import java.awt.BorderLayout;…

将Javascript带到边缘设备

Smart devices today are very similar to labour-saving gadgets a generation ago: Where previously everything got a power cord, now everything gets a chip. 如今的智能设备与上一代的省力小工具非常相似&#xff1a;以前所有设备都配有电源线&#xff0c;而现在所有设…

java 泛型 父子_使用通配符和泛型:完成父子类关系的List对象的类型匹配

泛型和通配符使用泛型和通配符都可以让一个方法所表示的算法逻辑适应多种类型。Java中具备继承关系的类A、B(A extends B)它们的集合List和List之间是没有继承关系的&#xff0c;可以使用泛型或通配符来让一个方法支持同时接受List和List。代码场景这里分别定义类Animal、Dog和…

重定向描述符

文件描符 缩写 描述 0 STDIN 标准输入 1 STDOUT 标准输出 2 STDERR 标准错误 1、重定向错误和数据 1234[rootlogicserver tmp]# ls -al data1 haha 2> qingyun.txt 1&g…

NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证

目录 开发环境  1、建立工程  2、目录结构  3、Express配置文件  4、Ejs模板  5、安装常用库及页面分离  6、路由  7、session  8、页面访问控制及提示JS是脚本语言&#xff0c;脚本语言都需要一个解析器才能运行。对于写在HTML页面里 的JS&#xff0c;浏览器充…

LeetCode-208 Implement Trie (Prefix Tree)

题目描述 Implement a trie with insert, search, and startsWith methods. 题目大意 实现对一棵树的插入、搜索以及前序查找操作。 &#xff08;树的每个节点代表一个小写字母&#xff0c;从根节点到叶节点代表一个完整的单词&#xff09; 示例 E Trie trie new Trie();trie.…

react组件生命周期_React组件生命周期-挂钩/方法介绍

react组件生命周期React components have several lifecycle methods that you can override to run your code at a particular time in the process.React组件具有几种生命周期方法&#xff0c;您可以重写它们以在流程中的特定时间运行代码。 In this video, Nick Karnik de…

(马世龙)Linux下CACTI完全搭建技术文档二

续&#xff08;马世龙&#xff09;Linux下CACTI完全搭建技术文档一 6.完成cacti的安装1. 首先检查一下rra/下面&#xff0c;有没有数据2. snmpwalk -v 2c -c public ServerIP if 用来测试被控对象(serverIP)是否开启了SNMP服务3. snmpwalk -v 2c ServerIP -c public .1.3.6.1.4…

项目经理如何管理情绪?这三本书管理书籍你必须要看

本文主要是介绍三本管理的书籍&#xff0c;需要全部书籍的可以加Q群375508415去拿走。里面很多大神的PMP资料。 大家有没有觉得项目经理有时像个政委&#xff0c;做员工思想工作&#xff1b; 有时像个HR&#xff0c;操心员工的稳定和发展&#xff1b; 有时像个咨询顾问&#xf…

java 外部接口调用 设计模式_《Java设计模式》之接口模式

-----------模式是思想的体现&#xff0c;而非具体的实现。抽象的讲&#xff0c;类的接口是类允许其他类对象访问的方法与字段集。接口通常代表一种承诺&#xff0c;即方法需要实现接口方法名表示的操作&#xff0c;遵循代码注释和其他文档说明&#xff0c;类的实现就是方法体中…

BFS(广度优先搜索)

Catch That Cow Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer …