1.why sharding?

我们都知道,信息行业发展日益迅速,积累下来的数据信息越来越多,互联网公司门要维护的数据日益庞大。设想一下,假如腾讯公司只用一个数据库的一张表格来存储所有qq注册用户的登录相关信息,毫不夸张的说,那好比就是一场灾难,腾讯少说都有好几个亿的用户,所有的信息都存储在一个数据库的一张表中,那么我们的sleect语句那得多么的消耗硬件资源,用户体验度那是相当的差的,基本上不能去运行了,那谁还去用qq,那怎么办呢,数据分割这时候就派上用场了,它根据数据的特性,将一张表单上的内容根据实际需求分割成多张表单,存储在不同的真实的服务器器上,能够做到指定用户访问指定的服务器,缩小表单,减小单个服务器的压力。其实这样做带来的好处还远不止缩小了表单的大小,来提高用户体验,其实,将数据分割,还可以减小锁表的概率,不会去锁整张表的内容,提高了表的可用率,当单台数据库服务器宕机了,也是是损坏了数据的一小部分,不会导致所有的数据都丢失,数据切割能带来这么多好处,何乐而不为呢?

取模和用户量分布计算
取值说明: user_id % 360 这个取模值均匀的分布到这12台DB,
所有server的库名相同,表结构保持一致,
DB_Server1 0~30度 用户数量为:2583354
DB_Server2 31~60度 用户数量为:2500020
DB_Server3 61~90度 用户数量为:2500020
DB_Server4 91~120度 用户数量为:2500019
DB_Server5 121~150度 用户数量为:2499990
DB_Server6 151~180度 用户数量为:2499990
DB_Server7 181~210度 用户数量为:2499990
DB_Server8 211~240 度 用户数量为:2499990
DB_Server9 241~270 度 用户数量为:2499990
DB_Server10 271~300 度 用户数量为:2499990
DB_Server11 301~330 度 用户数量为:2499990
DB_Server12 331~360 度 用户数量为:2416657

DB架构图
当第一个360度环形库,用户量超过3000万怎么办???开始扩容第二个360度环形库

2.数据原型

数据原形:一个数据库,用来存储用户的编号,姓名,以及地址(当然,你可以有多个数据库作为数据原形,可以用到垂直分割进行处理,这里直接用一个数据库作为数据原型进行数据水平切割处理)因为仅仅是去实现水平分割,不做读写分离、也不配置双机热备,所以仅仅需要三台机器,两台独立的mysql服务器,一台amoeba代理服务器即可。

3.环境介绍

Mysql_server1--IP:192.168.1.135(服务器1)
Msyql_serrver2---IP:192.168.1.136(从服务器2)
Amoeba_server--IP:192.168.1.137(代理服务器)

4、设置Mysql_server1 Mysql_server2 设置Amoeba远程访问授权

(首先授权登录mysql服务器的用户,两台mysql服务器都要进行授权)
mysql-->grant all privileges on *.* to amoeba@'%' identified by 'amoeba';
mysql-->flush privileges;

5、创建测试表

(1)在Mysql_server1 和mysql_server2 上。注意:两边的表结构以及表名是一样的.
创建test表
create table test (
user_id integer unsigned not null,
user_name varchar(45),
user_address varchar(100),
primary key (user_id)
)engine=innodb;  ·  
Query OK, 0 rows affected (0.01 sec

6.amoeba.xml相关配置(安装amoeba略,见前一篇mysql的读写分离)

<?xml version="1.0" encoding="gbk"?>

<!DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba:configuration xmlns:amoeba="">http://amoeba.meidusa.com/">

<!--
amoeba开放接口相关配置
-->
<server>
<!-- proxy server绑定的端口 -->
<property name="port">9006</property>

<!-- proxy server绑定的IP -->
<property name="ipAddress">192.168.1.137</property>

<!-- proxy server net IO Read thread size -->
<property name="readThreadPoolSize">20</property>

<!-- proxy server client process thread size -->
<property name="clientSideThreadPoolSize">30</property>

<!-- mysql server data packet process thread size -->
<property name="serverSideThreadPoolSize">30</property>

<!-- socket Send and receive BufferSize(unit:K) -->
<property name="netBufferSize">128</property>

<!-- Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm). -->
<property name="tcpNoDelay">true</property>

<!-- 对外验证的用户名 -->
<property name="user">amoeba</property>

<!-- 对外验证的密码 -->
<property name="password">aixocm</property>

<!-- query timeout( default: 60 second , TimeUnit:second) -->
<property name="queryTimeout">60</property>
</server>

<!--
每个ConnectionManager都将作为一个线程启动。
manager负责Connection IO读写/死亡检测
-->
<connectionManagerList>
<connectionManager name="defaultManager" class="com.meidusa.amoeba.net.MultiConnectionManagerWrapper">
<property name="subManagerClassName">com.meidusa.amoeba.net.AuthingableConnectionManager</property>

<!--
default value is avaliable Processors
<property name="processors">5</property>
-->
</connectionManager>
</connectionManagerList>

<dbServerList>
<!--
一台mysqlServer 需要配置一个pool,
如果多台 平等的mysql需要进行loadBalance,
平台已经提供一个具有负载均衡能力的objectPool:com.meidusa.amoeba.mysql.server.MultipleServerPool
简单的配置是属性加上 virtual="true",该Pool 不允许配置factoryConfig
或者自己写一个ObjectPool。
-->

<!--
mysql服务器授权相关设置
-->
<dbServer name="server1">

<!-- PoolableObjectFactory实现类 -->
<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
<property name="manager">defaultManager</property>

<!-- 真实mysql数据库端口 -->
<property name="port">3306</property>

<!-- 真实mysql数据库IP -->
<property name="ipAddress">192.168.1.135</property>

<property name="schema">test</property>

<!-- 用于登陆mysql的用户名 -->
<property name="user">amoeba</property>

<!-- 用于登陆mysql的密码 -->
<property name="password">amoeba</property>

</factoryConfig>

<!-- ObjectPool实现类 -->
<poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
<property name="maxActive">200</property>
<property name="maxIdle">200</property>
<property name="minIdle">10</property>
<property name="minEvictableIdleTimeMillis">600000</property>
<property name="timeBetweenEvictionRunsMillis">600000</property>
<property name="testOnBorrow">true</property>
<property name="testWhileIdle">true</property>
</poolConfig>
</dbServer>

<!--
mysql服务器授权相关设置
-->
<dbServer name="server2">

<!-- PoolableObjectFactory实现类 -->
<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
<property name="manager">defaultManager</property>

<!-- 真实mysql数据库端口 -->
<property name="port">3306</property>

<!-- 真实mysql数据库IP -->
<property name="ipAddress">192.168.1.136</property>

<property name="schema">test</property>

<!-- 用于登陆mysql的用户名 -->
<property name="user">amoeba</property>

<!-- 用于登陆mysql的密码 -->
<property name="password">amoeba</property>

</factoryConfig>

<!-- ObjectPool实现类 -->
<poolConfig class="com.meidusa.amoeba.net.poolable.PoolableObjectPool">
<property name="maxActive">200</property>
<property name="maxIdle">200</property>
<property name="minIdle">10</property>
<property name="minEvictableIdleTimeMillis">600000</property>
<property name="timeBetweenEvictionRunsMillis">600000</property>
<property name="testOnBorrow">true</property>
<property name="testWhileIdle">true</property>
</poolConfig>
</dbServer>

</dbServerList>
<queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
<property name="ruleConfig">${amoeba.home}/conf/rule.xml</property>
<property name="functionConfig">${amoeba.home}/conf/functionMap.xml</property>
<property name="ruleFunctionConfig">${amoeba.home}/conf/ruleFunctionMap.xml</property>
<property name="LRUMapSize">1500</property>

<property name="defaultPool">server1</property>
<!--
;默认地址池一定要开启
<property name="writePool">master</property>
<property name="readPool">slave</property>
<property name="needParse">true</property>
-->
</queryRouter>
</amoeba:configuration>

7.rule.xml相关配置

基于user_id的水平分割,360水平分割法,前提user_id是连续的。

<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE amoeba:rule SYSTEM "rule.dtd">

<amoeba:rule xmlns:amoeba="">http://amoeba.meidusa.com/">
<tableRule name="test" schema="test" defaultPools="server1,server2">

<rule name="rule1">
<parameters>user_id</parameters>
<expression><![CDATA[
user_id % 360 >=0 and user_id % 360 <=180         ;分成两份,(1-180)+360并且小于5000000存在一个数据库
]]></expression>
<defaultPools>server1</defaultPools>
<readPools>server1</readPools>
<writePools>server1</writePools>
</rule>

<rule name="rule2">
<parameters>user_id</parameters>
<expression><![CDATA[
user_id % 360 >=181 and user_id % 360 <=360     (181-360)+360并且小于5000000存在于一个数据库
]]></expression>
<defaultPools>server2</defaultPools>
<writePools>server2</writePools>
<readPools>server2</readPools>
</rule>
<!--
<rule name="rule4">
<parameters>ID</parameters>
<expression><![CDATA[ ID > 20000000 ]]></expression>
<defaultPools>server3</defaultPools>
</rule>

<rule name="rule3">
<parameters>ID,CREATE_TIME</parameters>
<expression><![CDATA[ID>4 or CREATE_TIME between to_date('2008-11-12 00:00:00.0000') and to_date('2008-12-10 00:00:00.0000') ]]></expression>
<defaultPools>server3</defaultPools>
</rule>
-->
</tableRule>

</amoeba:rule>

8.启动服务

#:nohup bash -x amoeba & 
这样的启动方法是为了方便查看启动的过程,会生成nohup.out的文件记录启动过程

重新启动服务需要先杀死已经启动的服务再重新启动服务

ps -ef|grep amoeba|awk '{print $2}'|xargs kill -9

9、插入测试数据

在Amoeba Server登录:
# mysql -uamoeba -paixocm -h 192.168.1.137 -P 9006
mysql->use test;
mysql->insert into test(user_id,user_name,user_address) values('1','user1','China');
特别提示,一定要将表的数组名带上,特别是用来作为水平分割的数组名,如果不接上,分割失败,会在两个服务器上全部插入数据。
mysql->insert into test(user_id,user_name,user_address) values('2','user1','China');
mysql->insert into test(user_id,user_name,user_address) values('3','user1','China');
mysql->insert into test(user_id,user_name,user_address) values('181','user1','China');
mysql->insert into test(user_id,user_name,user_address) values('182','user1','China');
mysql->insert into test(user_id,user_name,user_address) values('183','user1','China');

mysql_server1查看,user_id在1-180数据全部写入了server1
mysql_server2查看,user_id在181-360数据全部写入了server2

10.总结:

(1)、amoeba 是根据 sql 解析来进行水平切分的, 需要把切分的关键字段(这里是user_id),加入到insert  sql 语句 中。否则 切分规则无效。无效后,会在 server1, server2 均都插入数据。

(2)、amoeba插入数据的时候必须先use  dbname(比如要先use test库名,或者查询带上库名和表名,test.t_user) 否则插入数据会默认插到server1上面

(3)、在rule.xml 指定的ID范围,在插入数据user_id的时候。不能超过这个范围,否则分片无效,
比如定义的ID范围为:
1-500000号
insert into zyalvin(user_id,user_name,user_address)values('5000001','user1','China'); 如果插入ID超过5000000,变成了5000001的话那么这个数据将同时写到server1和server2 导致分片无效。

基于mysql数据库集群的360度水平切割的更多相关文章

  1. MySQL数据库集群进行正确配置步骤

    MySQL数据库集群进行正确配置步骤 2010-06-09 10:47 arrowcat 博客园 字号:T | T 我们今天是要和大家一起分享的是对MySQL数据库集群进行正确配置,我前两天在相关网站 ...

  2. Facebook揭密:如何让MySQL数据库集群自主运行

    Facebook运行着全球最大的MySQL数据库集群,该集群分布在两个大洲上的多个数据中心中数以千计的服务器上.让人不解的是,Facebook只动用了一个很小的团队来管理这个庞大的MySQL数据库集群 ...

  3. 生产环境MySQL数据库集群MHA上线实施方案

    生产环境MySQL数据库集群MHA上线实施方案 一.不停库操作 1.在所有节点安装MHAnode所需的perl模块(需要有安装epel源) yum install perl-DBD-MySQL -y ...

  4. mysql数据库集群

    mysql数据库集群主要有2种常用方案: replication:速度快.弱一致性.适合保存低价值的数据,主要应用于日志.新闻.帖子等系统. PXC:速度慢.强一致性.适合保存高价值的数据,主要应用于 ...

  5. 【Data Cluster】真机环境下MySQL数据库集群搭建

    真机环境下MySQL-Cluster搭建文档  摘要:本年伊始阶段,由于实验室对不同数据库性能测试需求,才出现MySQL集群搭建.购置主机,交换机,双绞线等一系列准备工作就绪,也就开始集群搭建.起初笔 ...

  6. openstack controller ha测试环境搭建记录(四)——配置mysql数据库集群

    内容正式开始前,我已经在集群中添加了新的节点controller1(IP地址为10.0.0.14). 在所有节点上安装软件:# yum install -y mariadb-galera-server ...

  7. 数据库集群 MySQL主从复制

    MySQL主从复制 本节内容我们联系使用MySQL的主从复制功能配置Master和Slave节点,验证数据MySQL的数据同步功能. 因为要使用多个MySQL数据库,所以不建议在电脑上安装多个MySQ ...

  8. docker应用-6(mysql+mycat 搭建数据库集群)

    上一节,通过使用overlay网络,搭建了跨主机的docker容器集群.下面,在这个跨主机的docker容器集群环境下,搭建mysql 数据库集群. mysql主从自动备份和自动切换 从数据安全性考虑 ...

  9. mycat数据库集群系列之mysql主从同步设置

    最近在梳理数据库集群的相关操作,现在花点时间整理一下关于mysql数据库集群的操作总结,恰好你又在看这一块,供一份参考.本次系列终结大概包括以下内容:多数据库安装.mycat部署安装.数据库之读写分离 ...

随机推荐

  1. 学习-go语言坑之for range

    引用自 http://studygolang.com/articles/9701 go只提供了一种循环方式,即for循环,在使用时可以像c那样使用,也可以通过for range方式遍历容器类型如数组. ...

  2. hdu2469(计算几何)

    枚举所有可能的半径,然后将所有满足这个半径的点按角度(与x轴正半轴的夹角)排序. 然后一遍扫描求出在这个半径下选k个点所需的最小面积 . 思路还是比较简单,实现略有些繁琐. 要先将点的坐标转换为角度. ...

  3. [LintCode] 两个排序数组的中位数

    class Solution { public: /** * @param A: An integer array. * @param B: An integer array. * @return: ...

  4. DTD的学习和理解

    看log4j的官方文档,上面说提供了XML格式的配置,但是没有XML具体示例.发现文档中说的是一个DTD文档,但我根本不知道DTD是什么,于是就简单了解一下.顺带做一下笔记. 注:结合笔记看log4j ...

  5. hdu 1257 最少拦截系统【贪心 || DP——LIS】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  6. Python菜鸟之路:Django 数据验证之钩子和Form表单验证

    一.钩子功能提供的数据验证 对于数据验证,django会执行 full_clean()方法进行验证.full_clean验证会经历几个步骤,首先,对于model的每个字段进行正则验证,正则验证通过后, ...

  7. Java基础语法 - 面向对象 - static 关键字

    使用static关键字修饰的变量.常量和方法分别被称作静态变量.静态常量和静态方法,也被称作类的静态成员 静态变量 使用static修饰过的类变量称为静态变量 该变量需要使用类名.变量名进行调用,不能 ...

  8. 模块 - json/pickle/shelve/xml/configparser

    序列化: 序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes. 为什么要序列化: 有种办法可以直接把内存数据(eg:10个列表,3 ...

  9. sklearn.svm包中的SVC(kernel=”linear“)和LinearSVC的区别

    参考:https://stackoverflow.com/questions/45384185/what-is-the-difference-between-linearsvc-and-svckern ...

  10. Go语言版本的helloworld

    新建一个project,然后建立一个main目录,在main目录下新建一个go类文件:main.go 内容如下: package main import "fmt" func ma ...