mysql分表 动态扩容_数据库hash分表后的扩容方案

postgres的hash分表不停机扩容方案

原来我们hash分表之后,数据扩容采用的是rehash,这样迁移全部的数据,比较麻烦。

本次扩容利用hash环原理,并在此基础上做一些适应性的改动。

首先假定哈希环的范围为0-1023,总共1024的数字,这个可以根据项目情况扩大或者减小。

然后假定表"test"中有一个字段"test_col",我们根据这一个字段进行分表,因为hash环的范围是0-1023,所以hash之后取模将hash的范围固定在0-1023之间,如abs(mod(hashtext(test_col::text), 1024)),abs是为了防止数据出现负值。

初始化分表

bd72de8cf8da

数据不均衡.JPG

假设我们初始化了4张表,table_0、table_1、table_2、table_3,hash取模之后的区间[0,1)的数据存在table_0,[1,2)之间的存在table_1中,[2,3)之间的存在table_2中,[3,1023]之间的存在table_3中,但又因hash取模后的数是整数,因此0->table_0,1->table_1,2->table_2,[3,1023]->table_3,很明显出现了数据不均衡。

建立虚拟映射

bd72de8cf8da

初始化.JPG

这里我们采用取余的方式建立虚拟映射,即abs(mod(hashtext(test_col::text), 1024))%4,余数是几就插入到几号表中,hash环上的table_0-n,table_1-n,table_2-n,table_3-n,就是虚拟映射用的表,每个实体表对应了(1024-4)/4张虚拟表,因为1024是4的整数倍,所以在实际数据插入的时候是可以均匀插入的。

扩容

如上所示,我们已经可以利用hash环将我们的数据存在指定的分表中了,但是数据量增加的时候,还是有扩容的需求的,所以重点来了,如下图所示,我们将4张表扩容成8张表了,映射关系变更为abs(mod(hashtext(test_col::text), 1024))%8,即原先4%4=0(12,20...,1020),这个表中的数据迁移到表4中,原先5%4=1(13,21...,1021),中的数据迁移到表5中,原先6%4=2(14,22...,1022),中的数据迁移到表6中,原先7%4=3(15,23...,1023),中的数据迁移到表7中,其中有(0,8,...,1016),(1,9,...,1017),(2,10,...,1018),(3,11,...,1019)这些映射上的数据是不需要迁移的,因此只需要迁移一半的数据即可。

bd72de8cf8da

扩容.JPG

脚本语句

(1)初始化分表语句

## 分表语句

do language plpgsql

$$

declare

parts int := 4;

begin

for i in 0..parts-1 loop

execute format('create table test%s (like test including all) inherits (test)', i);

execute format('alter table test%s add constraint ck check((abs(mod(hashtext(test_col),1024))%%4)=%s)', i, i);

end loop;

end;

$$;

## 触发器函数

create or replace function ins_test() returns trigger as

$$

declare begin

case (abs(mod(hashtext(NEW.test_col),1024))%4)

when 0 then

insert into test0 values (NEW.*);

when 1 then

insert into test1 values (NEW.*);

when 2 then

insert into test2 values (NEW.*);

when 3 then

insert into test3 values (NEW.*);

else

return NEW;

end case;

return null;

end;

$$

language plpgsql strict;

## 为空保护

create trigger test_ins_tg before insert on test for each row when (NEW.test_col is not null) execute procedure ins_test();

## 查询时拼接

and (abs(mod(hashtext(test_col::text), 1024))%4)=(abs(mod(hashtext(#{testCol}::text), 1024))%4)

(2)扩容脚本-1

do language plpgsql

$$

declare

parts int := 8;

begin

for i in 4..parts-1 loop

execute format('create table test%s (like test including all) inherits (test)', i);

execute format('alter table test%s add constraint ck check((abs(mod(hashtext(test_col),1024))%%8)=%s)', i, i);

end loop;

end;

$$;

## 触发器函数

create or replace function ins_test() returns trigger as

$$

declare begin

case (abs(mod(hashtext(NEW.test_col),1024))%8)

when 0 then

insert into test0 values (NEW.*);

when 1 then

insert into test1 values (NEW.*);

when 2 then

insert into test2 values (NEW.*);

when 3 then

insert into test3 values (NEW.*);

when 4 then

insert into test0 values (NEW.*);

when 5 then

insert into test1 values (NEW.*);

when 6 then

insert into test2 values (NEW.*);

when 7 then

insert into test3 values (NEW.*);

else

return NEW;

end case;

return null;

end;

$$

language plpgsql strict;

## 查询时拼接

and (abs(mod(hashtext(test_col::text), 1024))%8)=(abs(mod(hashtext(#{testCol}::text), 1024))%8)

(3)扩容脚本-2

因为原先的分表中constraint定义的是%4,这里需要改成%8

alter table test0 add constraint ck check((abs(mod(hashtext(test_col),1024))%%8)=0)

alter table test0 add constraint ck check((abs(mod(hashtext(test_col),1024))%%8)=1)

alter table test0 add constraint ck check((abs(mod(hashtext(test_col),1024))%%8)=2)

alter table test0 add constraint ck check((abs(mod(hashtext(test_col),1024))%%8)=3)

(4)数据转移

如要将表test0中的要转移的数据查出来,然后存在新表中。

SELECT * FROM test0 where (abs(mod(hashtext(test_col::text), 1024))%8)=4

注意点

(1)这里采用的数据扩容方式是成倍扩容,而1024刚好符合我们的成倍扩容方式,不会造成数据倾斜。

(2)表数量是会动态变更的,如果服务需要动态扩容的话,这个值不应该写死在代码里面,应该支持动态变更。

(3)扩容的时候还做不到对整体系统无影响,因此只能选在夜深人静时。

如果各位有更好的方法,请多多指教,谢谢。

如果各位有更好的方法,请多多指教,谢谢。

如果各位有更好的方法,请多多指教,谢谢。

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

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

相关文章

php mysql长连接聊天室_PHP之探索MySQL 长连接、连接池

PHP连接MysqL的方式,用的多的是MysqL扩展、MysqLi扩展、pdo_MysqL扩展,是官方提供的。PHP的运行机制是页面执行完会释放所有该PHP进程中的所有资源的,如果有多个并发访问本地的测试页面 http://127.0.0.1/1.php 根据PHP跟web服务器的不同,会开…

python 读取地震道头数据_python地震数据可视化详解

本文实例为大家分享了python地震数据可视化的具体代码,供大家参考,具体内容如下准备工作:在windows10下安装python3.7,下载参考源码到本地。1. demo绘图测试demo绘图指令cmd> python seisplot.py --demo问题1)缺少依赖包File &…

java程序员 css_Java程序员从笨鸟到菜鸟之(十七)CSS基础积累总结(下)

七.组织元素(span和div)span和div元素用于组织和结构化文档,并经常联合class和id属性一起使用。在这一课中,我们将进一步探究span和div的用法,因为这两个HTML元素对于CSS是很重要的。用span组织元素用div组织元素用span组织元素span元素可以说…

java set泛型_Java 集合二 泛型、Set相关

泛型1、在定义一个类的方法时,因为不确定返回值类型,所以用一个符号代替,这个符号就是泛型eg:ArrayList list new ArrayList();2、泛型的好处:1、提高了数据的安全性,将运行时的问题提前暴露在编译阶段2、避免了强转的…

java gson_Java 中 Gson的使用

JSON 是一种文本形式的数据交换格式,它比XML更轻量、比二进制容易阅读和编写,调式也更加方便;解析和生成的方式很多,Java中最常用的类库有:JSON-Java、Gson、Jackson、FastJson等一、Gson的基本用法Gson提供了fromJson() 和toJson…

java web 集成dom4j_[JavaWeb基础] 031.dom4j写入xml的方法

上一篇我们讲述了dom4j读取xml的4种方法,甚是精彩,那么怎么样写入xml呢?我们直接看下源码实现。public static void main(String[] args) throws Exception {// 创建文档Document document DocumentHelper.createDocument();// 设置编码docu…

java servlet 调试日志 logger sae_java servlet 调试日志 lo

java servlet 调试日志 lo[2021-02-10 08:32:08] 简介:php去除nbsp的方法:首先创建一个PHP代码示例文件;然后通过“preg_replace("/(\s|\&nbsp\;| |\xc2\xa0)/", " ", strip_tags($val));”方法去除所有nbsp即可。推荐&#x…

求java简单计算器源代码_java简单计算器源代码

简单计算器代码package calcultorthree;import java.awt.BorderLayout;//导入边界布局管理器类import java.awt.GridLayout;//导入网格布局管理器类import java.awt.TextField;//导入文本区域类import java.awt.event.ActionEvent;//导入事件类import java.awt.event.ActionLis…

java遍历斐波纳契数列_详解循环、迭代、递归、分治(Leet Code 509 斐波那契数列),实际运用...

Multiple solutions of Fibonacci (Python or Java)本章是用英文写的,作为或想成为一名优秀的攻城狮,习惯阅读英文文档将使你受益良多。例如更好的查看最新版的官方文档、与国外友人交流、等等 其实英文的生词也并不多,其中90%的英文都在代码…

java 二分查找 排序_java 冒泡排序 二分查找

下面这个程序是先定义一个整型数组,然后将其中的元素反序赋值,再用冒泡排序进行排序以后用二分查找来查找其中是否有某个数,返回值为-1时表示这个数可能小于这个数组的最小值或大小这个数组的最大值,-2表示这个数比这个数组的最小…

php里h和h的区别吗,编码h264h和h264b有什么区别

区别如下:1、版本H.265是新的编码协议,也即是H.264的升级版。H.265标准保留H.264原来的某些技术,同时对一些相关的技术加以改进。新技术使用先进的技术用以改善码流、编码质量、延时和算法复杂度之间的关系,达到最优化设置。2、储…

php 抽象类 静态方法吗,php中的抽象类和静态方法是什么

php中的抽象类是指:在class前加了abstract关键字且存在抽象方法的类,它不能被直接实例化;静态方法是指:被static关键字修饰的方法,静态方法用于操作静态属性。抽象类抽象类是指在 class 前加了 abstract 关键字且存在抽…

centos 怎样下载php,centos下怎样安装软件

centos下安装软件的方法是:centos安装软件的命令1、rpm包的安装1.安装一个包# rpm -ivh2.升级一个包# rpm -Uvh3.移走一个包# rpm -e4.安装参数--force 即使覆盖属于其它包的文件也强迫安装--nodeps 如果该RPM包的安装依赖其它包,即使其它包没装&#xf…

php post 微信沙箱,微信支付平台错误:获取沙箱密钥失败,确保交易密钥是

按官方提示进行获取沙箱密钥的时候,久试不爽,总是提示错误 :“获取沙箱密钥失败,确保交易密钥是否正确”。这个纯粹是微信平台挖的坑呀,文档没有详细的进行一些讲解,也没有提示需要key,下面来说…

linux显示磁盘使用情况命令,Linux中监控磁盘分区和使用情况的几个工具

导读在文章中将讨论Linux中可用于监视磁盘使用情况的命令行实用程序,提供有关总大小容量、已用总量、文件系统信息和分区信息等。让我们看看这些工具如何帮助检索这些信息df命令df是一个Linux命令行实用程序,用于监视Linux磁盘使用情况。df命令显示文件系…

linux网络是文件吗,linux网络配置文件是什么意思

离开了么放得下我么回来了么还会爱我么新兵答主07-22TA获得超过2383个赞网卡的配置:1.网卡配置文件对于网卡信息的配置通常包括:配置IP地址、子网掩码和网关。网卡信息保存在网卡配置文件中。网卡配置文件位于/etc/sysconfig/network-scripts目录下。一块…

cd linux给u盘安装程序,使用U盘安装CDlinux

3、先把u盘插在电脑上与电脑连接,格式化成“FAT”文件系统,更改卷标为“CDLINUX”,之后再打开UltraISO工具进行写入:a、这里把你下载好的CDlinux文件打开。b、点击“写入硬盘映像”c、这里直接默认就好,点击“写入”4、…

zenmap扫描出来linux,如何在Linux上使用NMAP安全扫描器

Nmap是一个免费的开源网络发现和安全审计实用程序,在Linux用户社区中被广泛使用,因为它使用起来非常强大。 Nmap通过在特定目标(通过IP)发送数据包,并通过解释传入的数据包来确定哪些帖子被打开/关闭,扫描系统上运行什么服务&…

c语言小明今年16岁,C语言1.爷爷对小明说:我现在的年龄是你的7倍,过几年是你的6倍,再过若干年就分别是你的5倍,4倍,3倍,2倍.你知道爷爷和小明现在的年龄吗?...

满意答案ta_meng2013.06.15采纳率&#xff1a;49% 等级&#xff1a;12已帮助&#xff1a;5126人#include void main(){int i,j,k;int t60,t50,t40,t30,t20; //用于标记是否达到过这些要求&#xff0c;C语言貌似没有bool类型吧for (i21;i<200;i7) //爷爷的年龄为i{ji/7;…

Android usb 权限广播,android10.0 USB弹窗权限流程解析

USB请求权限流程1. 新建activity&#xff0c;获取UsbManager usbManager (UsbManager) getSystemService(Context.USB_SERVICE)2. 获取所以的USB设备HashMap map usbManager.getDeviceList()3. 过滤别的USB设备&#xff0c;拿到自己USB的USBDevice类&#xff0c;然后请求USB权…