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 &…

在MySQL查询山东省男生信息_MySQL-查询

来一波英语单词解释(意思)create 创建show 显示database 数据库use 使用select 选择table 表from 来自…distinct 消除重复行as 同样地(用于其别名)where 范围like 模糊查询rlike 正则查询In 范围查询not in 不非连续的范围之内between ... and …表示…

java 导入world数据_java读取world文件,把world文件中的内容,原样输出到页面上。...

POI,处理可以。样式在Java代码中添加就可以。给了一个例子这个是Excel的。package cn.com.my.common;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.sql.Connection;import java.sql.ResultSet…

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

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

redlock java_Redlock分布式锁

这篇文章主要是对 Redis 官方网站刊登的 Distributed locks with Redis 部分内容的总结和翻译。什么是 RedLockRedis 官方站这篇文章提出了一种权威的基于 Redis 实现分布式锁的方式名叫 Redlock,此种方式比原先的单节点的方法更安全。它可以保证以下特性&#xff1…

java 两个数组交叉_java – 如何交叉两个没有重复的排序整数数组?

这个问题本质上减少到一个连接操作,然后是一个过滤器操作(删除重复,只保留内部匹配).由于输入都已经排序,所以可以通过O(O(size(a)size(b))的merge join来有效地实现连接.过滤器操作将为O(n),因为连接的输出被排序,并且要删除重复项,所有您需要做的是检查每个元素是否与之​​前…

java retentionpolicy_Java注解之如何利用RetentionPolicy.SOURCE生存周期

上一篇文章简单讲了下Java注解的学习之元注解说明,学习了Java注解是如何定义的,怎么使用的,但是并没有介绍Java的注解是怎么起作用的,像Spring Boot里面的那些注解,到底是怎么让程序这样子运行起来的?特别是…

在java程序中定义的类有两种成员_java试题 急需答案 谢谢!!!

三、填空(每小题2分,共10分)1.在Applet中,创建一个具有10行45列的多行文本区对象ta的语句为:2.创建一个标识有“关闭”字样的标签对象gb的语句为。3.方法是一种仅有方法头,没...三、填空(每小题…

java 同步 变量,在java中的对象上同步,然后更改同步的变量的值

I came across a code like thissynchronized(obj) {obj new Object();}Something does not feel right about this , I am unable to explain, Is this piece of code OK or there is something really wrong in it, please point it out.Thanks解决方案Its probably not wha…

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

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

java annotation 实现_在Java中如何实现自己的annotation

1. 先定义annotation2. 使用annotation例子:import java.lang.annotation.*;import java.lang.reflect.Method;Target(ElementType.METHOD)Retention(RetentionPolicy.RUNTIME)interface Test {String info() default "";}class Annotated {Test(info &q…

登录界面拦截java_java拦截通过url访问页面,必须通过登录页面访问目标页面

在web.xml中配置过滤:LoginFiltercom.verification.action.LoginFilterLoginFiltery/form/dealParse.do/* 拦截所有请求/.do 拦截以“.do”结尾的请求/index.jsp 拦截指定的jsp/artery/form/* 拦截该目录下的所有请求等等拦截器,拦截请求类&#xf…

python textwrap_[Python标准库]textwrap——格式化文本段落

textwrap——格式化文本段落作用:通过调整换行符在段落中出现的位置来格式化文本。 Python 版本:2.5 及以后版本 需要美观打印时,可以用 textwrap 模块来格式化要输出的文本。这个模块允许通过编程提供类似段落自动换行或填充…

java 字符串 1_java 字符串操作大全1

1、length() 字符串的长度例:char chars[]{a,b.c};String snew String(chars);int lens.length();2、charAt() 截取一个字符例:char ch;ch"abc".charAt(1); 返回b3、getChars() 截取多个字符void getChars(int sourceStart,int sourceEnd,char…

java实现权限_Java实现权限管理的两种方式

编辑特别推荐:种方式:利用filter、xml文件和用户信息表配合使用来实现权限管理。1.过滤器filterpackage cn.com.aaa.bbb.filter;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Iterator;import java.util.List…

java 输入16进制_尝试使用十六进制输入来使用小端和大端

我试图用这两个原型编写C函数:int extract_little (char* str, int ofset, int n);int extract_big(char* str, int ofset, int n);现在一般的想法是我需要从地址str ofset开始以两种格式返回一个n字节整数 . 附: Ofset还没有做任何事情,我计…

java gson_Java 中 Gson的使用

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

spring注入普通java类_普通java类如何取得注入spring Ioc容器的对象

[除了使用XML配置外,还可以选择使用基于注解(annotation)的配置方式,其依赖于字节码来织入组件。注解注入在XML注入之前完成,因此在XML配置中可以重载注解注入的属性。一、建一个SpringUtil类package com.ceopen.eoss.spring; import org.spr…

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

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