[转]千万级别mysql合并表快速去重

目标:

现有表a和b,把两个表中的数据合并去重到c表中。其中a和b表中数据量大概在2千万左右。

基本情况

操作系统版本:CentOS release 5.6 64位

操作系统内存:8G

数据库版本:5.1.56-community 64位

数据库初始化参数:默认

数据库表和数据量

表a:

mysql> desc a2kw;+——-+————-+——+—–+———+——-+

| Field | Type        | Null | Key | Default | Extra |

+——-+————-+——+—–+———+——-+

| c1    | varchar(20) | YES  | MUL | NULL         |

| c2    | varchar(30) | YES     | NULL         |

| c3    | varchar(12) | YES     | NULL         |

| c4    | varchar(20) | YES     | NULL         |

+——-+————-+——+—–+———+——-+

4 rows in set (0.00 sec)

表b

mysql> desc b2kw;+——-+————-+——+—–+———+——-+

| Field | Type        | Null | Key | Default | Extra |

+——-+————-+——+—–+———+——-+

| c1    | varchar(20) | YES     | NULL         |

| c2    | varchar(30) | YES     | NULL         |

| c3    | varchar(12) | YES     | NULL         |

| c4    | varchar(20) | YES     | NULL         |

+——-+————-+——+—–+———+——-+

4 rows in set (0.00 sec)

 

a和b表的数据概况如下

mysql> select * from a2kw limit 10;+———–+———–+——+———-+

| c1        | c2        | c3   | c4       |

+———–+———–+——+———-+

| 662164461 | 131545534 | TOM0 | 20120520 |

| 226662142 | 605685564 | TOM0 | 20120516 |

| 527008225 | 172557633 | TOM0 | 20120514 |

| 574408183 | 350897450 | TOM0 | 20120510 |

| 781619324 | 583989494 | TOM0 | 20120510 |

| 158872754 | 775676430 | TOM0 | 20120512 |

| 815875622 | 631631832 | TOM0 | 20120514 |

| 905943640 | 477433083 | TOM0 | 20120514 |

| 660790641 | 616774715 | TOM0 | 20120512 |

| 999083595 | 953186525 | TOM0 | 20120513 |

+———–+———–+——+———-+

10 rows in set (0.01 sec)

基本步骤

1、在B表上创建索引

mysql> select count(*) from b2kw;+———-+

| count(*) |

+———-+

| 20000002 |

+———-+

1 row in set (0.00 sec)

mysql> create index ind_b2kw_c1 on  b2kw(c1);

Query OK, 20000002 rows affected (1 min 2.94 sec)

Records: 20000002  Duplicates: 0  Warnings: 0

数据量为:20000002 ,时间为:1 min 2.94 sec

2、把a、b分别插入中间表temp表中

创建中间表mysql> create table temp  select * from c2kw where 1=2;

Query OK, 0 rows affected (0.00 sec)

Records: 0  Duplicates: 0  Warnings: 0

插入数据

mysql> insert into temp  select * from a2kw;

Query OK, 20000002 rows affected (13.23 sec)

Records: 20000002  Duplicates: 0  Warnings: 0

mysql> insert into temp  select * from b2kw;

Query OK, 20000002 rows affected (13.27 sec)

Records: 20000002  Duplicates: 0  Warnings: 0

mysql> select count(*) from temp;

+———-+

| count(*) |

+———-+

| 40000004 |

+———-+

1 row in set (0.00 sec)

数据量为:40000004 ,时间为:26.50 sec

3、temp建立联合索引,强制索引去掉重复数据

mysql> create index ind_temp_c123 on temp(c1,c2,c3);Query OK, 40000004 rows affected (3 min 43.87 sec)

Records: 40000004  Duplicates: 0  Warnings: 0

查看执行计划

mysql> explain select c1,c2,c3,max(c4) from temp FORCE INDEX (ind_temp_c123) group by c1,c2,c3 ;

+—-+————-+——-+——-+—————+—————+———+——+———-+——-+

| id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows     | Extra |

+—-+————-+——-+——-+—————+—————+———+——+———-+——-+

1 | SIMPLE      | temp  | index | NULL          | ind_temp_c123 | 71      | NULL | 40000004 |       |

+—-+————-+——-+——-+—————+—————+———+——+———-+——-+

1 row in set (0.05 sec)

mysql> insert into c2kw select c1,c2,c3,max(c4) from temp FORCE INDEX (ind_temp_c123) group by c1,c2,c3 ;

Query OK, 20000004 rows affected (2 min 0.85 sec)

Records: 20000004  Duplicates: 0  Warnings: 0

实际大约花费实际为:6 min

4、删除中间表

mysql> drop table temp;Query OK, 0 rows affected (0.99 sec)

实际大约花费实际为:1 sec

5、建立c索引

mysql> create index ind_c2kw_c1 on c2kw(c1);Query OK, 20000004 rows affected (49.74 sec)

Records: 20000004  Duplicates: 0  Warnings: 0

mysql> create index ind_c2kw_c2 on c2kw(c2);

Query OK, 20000004 rows affected (1 min 47.20 sec)

Records: 20000004  Duplicates: 0  Warnings: 0

mysql> create index ind_c2kw_c3 on c2kw(c3);

Query OK, 20000004 rows affected (2 min 42.02 sec)

Records: 20000004  Duplicates: 0  Warnings: 0

实际大约花费实际为:5分钟

6、清空a、b表

mysql> truncate table a2kw;Query OK, 0 rows affected (1.15 sec)

mysql> truncate table b2kw;

Query OK, 0 rows affected (1.34 sec)

实际大约花费实际为:3sec

一共花费的时间大概在15分钟左右

转自:http://blog.sina.com.cn/s/blog_5755b8ed0101err7.html

关于使用sysbench测试数据库的负载情况

1.sysbench 简述:
   sysbench是一个模块化的、跨平台、多线程基准测试工具,主要用于评估测试各种不同系统、参数下的数据库负载情况。它主要包括以下几种方式的测试:
(1).cpu性能
(2).磁盘io性能
(3).调度程序性能
(4).内存分配及传输速度
(5).POSIX线程性能
(6).数据库性能(OLTP基准测试)
         目前sysbench主要支持 mysql,pgsql,oracle 这3种数据库
   # 注:不要认为sysbench安装很简单,其实蛮复杂的,动不动就报错,最下面了摘录了报错,基本上都能解决问题
2.sysbench的安装
  (2).安装依赖环境:
        yum -y install gcc automake libtool
    #    以下步骤,仅针对用rpm包默认安装mysql执行的操作,需要安装mysql,mysql-server,mysql-libs,mysql-devel,不然会报错
       yum -y install mysql mysql-server mysql-libs mysql-devel
  (3).解压安装sysbench
        tar -xf  sysbench-0.4.12.tar.gz
        cd sysbench-0.4.12
        ./autogen.sh
        ./configure
        make
        make install
# 注:
   如果想要让 sysbench 支持 pgsql/oracle 的话,就需要在编译的时候加上参数:–with-pgsql 或者 –with-oracle,这2个参数默认是关闭的,只有 MySQL 是默认支持的。
# 如果你的mysql是自己通过源码编译安装的,则使用如下方法,指定mysql的函数库位置和头文件位置
      ./configure –with-mysql-includes=/usr/local/mysql/include  –with-mysql-libs=/usr/local/mysql/lib
# –with-mysql-includes指定函数库位置
# –with-mysql-libs指定头文件位置
3.性能测试:
(1).cpu性能测试
     sysbench –test=cpu –cpu-max-prime=20000 run
    # cpu测试主要是进行素数的加法运算,在上面的例子中,指定了最大的素数为 20000,自己可以根据机器cpu的性能来适当调整数值,主要看total time所花费的时间
    # sysbench –test=cpu –num-threads=`grep “processor” /proc/cpuinfo | wc -l` –cpu-max-prime=200000 run
    # grep “processor” /proc/cpuinfo | wc -l :获取cpu的线程数
(2).线程测试
     sysbench –test=threads –num-threads=64 –thread-yields=100 –thread-locks=2 run
    # thread-locks小于线程数除以2,lock越少,处理时间越长。
(3).磁盘IO性能测试[主要看每秒请求数(request)和总体的吞吐量(total),这两个参数对评估磁盘性能有帮助]
    # 初识准备
     sysbench –test=fileio –num-threads=16 –file-total-size=3G –file-test-mode=rndrw prepare
    # 运行
     sysbench –test=fileio –num-threads=16 –file-total-size=3G –file-test-mode=rndrw run
    # 清空测试数据
     sysbench –test=fileio –num-threads=16 –file-total-size=3G –file-test-mode=rndrw cleanup
    # 上述参数指定了最大创建16个线程,创建的文件总大小为3G,文件读写模式为随机读写。
    # seqwr 顺序写 / seqrewr 连续改写 / seqrd 连续读 / rndrd 随机读取 / rndwr 随机写 / rndrw 结合随机读/写
(4).内存测试
     sysbench –test=memory –memory-block-size=8k –memory-total-size=4G run
    # 上述参数指定了本次测试整个过程是在内存中传输 4G 的数据量,每个 block 大小为 8K。
(5).OLTP测试
官方测试范例:
    # 准备数据
     sysbench  –test=oltp –mysql-table-engine=innodb –oltp-table-size=5000000 –mysql-user=root –mysql-password=kongzhong –mysql-socket=/var/lib/mysql/mysql.sock  prepare
    # 测试
    sysbench  –test=oltp –mysql-table-engine=innodb –oltp-table-size=5000000 –mysql-user=root –mysql-password=kongzhong –mysql-socket=/var/lib/mysql/mysql.sock  run
    # 删除数据
    sysbench  –test=oltp –mysql-table-engine=innodb –oltp-table-size=5000000 –mysql-user=root –mysql-password=kongzhong –mysql-socket=/var/lib/mysql/mysql.sock  cleanup
4.报错及解决方式:
(1). make 时报错:
      drv_mysql.c:35:19: mysql.h: No such file or directory
   # 因为找不到mysql 的头文件,安装mysql-devel、mysql-libs这两个rpm包就可以了[这个只针对使用rpm包安装mysql的]
   # 如果是源码编译安装的,要指定: –with-mysql-includes=*****  –with-mysql-libs=****
   # 如: ./configure –with-mysql-includes=/usr/local/mysql/include –with-mysql-libs=/usr/local/mysql/lib
(2).make 时报错:
     ../libtool: line 838: X–tag=CC: command not found
     ../libtool: line 871: libtool: ignoring unknown tag : command not found
     ../libtool: line 838: X–mode=link: command not found
     ../libtool: line 1004: *** Warning: inferring the mode of operation is deprecated.: command not found
     ../libtool: line 1005: *** Future versions of Libtool will require –mode=MODE be specified.: command not found
     ../libtool: line 2231: X-g: command not found
     ../libtool: line 2231: X-O2: command not found
   # 这个问题,一般只要先运行一次autogen.sh,然后再configure,make就可以了;
   # 如果还是不能解决,是因为sysbench自带的libtool 工具版本太旧。 安装一个新版本的libtool,然后,复制libtool覆盖sysbench下的libtool,然后直接make[千万不要再./configure,否则libtool又被恢复成老版的libtool]
   # 如:cp /usr/bin/libtool ~/sysbench-0.4.12/
(3).安装完成后,如果在运行时出现下面的错误提示:
     sysbench: error while loading shared libraries: libmysqlclient_r.so.18: cannot open shared object file: No such file or directory
   # 使用下面的命令查看libmysqlclient_r.so.18是否存在
   #   find / -name “libmysqlclient_r.so.18” -print
   # 如果存在的话,网上说做软连接,我试过没用,于是使用下面的方法,就可以了,大家可以试试
   # export LD_LIBRARY_PATH=/usr/local/mysql/lib

关于mysql升级为mariadb

随着mysql的逐渐闭源,mysql的迁移势在必行,google、维基等公司都大力推行mariadb

下面做一个简单的mysql升级,将mysql 5.1升级到mariadb 5.5

1.配置mariadb的yum源

  1. [root@stu91 ~]# vim /etc/yum.repos.d/mariadb.repo  
  2. # yum源的内容如下:  
  3. [mariadb]  
  4. name = MariaDB  
  5. baseurl = http://yum.mariadb.org/5.5/rhel6-amd64  
  6. enabled = 1  
  7. gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB  
  8. gpgcheck=1  

2.停止mysql 服务

  1. [root@stu91 ~]# /etc/init.d/mysqld stop  

3.卸载mysql(这个之前最好备份数据库)

  1. [root@stu91 ~]# yum remove mysql mysql-server mysql-libs  

4.安装mariadb5.5【关于maridb的yum源,相信大家都配置好了】

  1. [root@stu91 ~]# yum -y install MariaDB-server MariaDB-client  

5.安装完成后,启动mariadb

  1. [root@stu91 ~]# /etc/init.d/mysql start  

6.登陆mariadb数据库

  1. [root@stu91 ~]# mysql  
  2. Welcome to the MariaDB monitor. Commands end with ; or \g.  
  3. Your MariaDB connection id is 8  
  4. Server version: 5.5.34-MariaDB MariaDB Server  
  5.   
  6. Copyright (c) 2000, 2013, Oracle, Monty Program Ab and others.  
  7. Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.  
  8.   
  9. MariaDB [(none)]> show databases;  

7.升级mariadb【此步必须做,网上有人说此步不需要做,那是因为他们没有遇到问题,这步不做,你的授权会有问题】

  1. [root@stu91 ~]# mysql_upgrade -p  

# 注:

到这里mysql就升级为mariadb了,但是,卸载mysql再升级总觉得不好,于是尝试网上方法不卸载mysql升级,但总是报错,提示有冲突,下面把网上的方法贴上,但是我是没升级上,各位如果有升级上的可以给予指导。

mysql 5.5版本升级为mariadb 5.5,使用下面方法,报同样的错[mariadb 5.1才出来时,我记得是可以直接升级的]

  1. [root@stu91 ~]# yum update –skip-broken  
  2. # MariaDB 相关安装包会被安装,不需要的 MySQL 包将被卸载,并且升级之后不需要对系统进行修补了。  

报错:

error

mysql 数据库自动备份

在数据库的管理过程中,经常涉及到数据库的备份问题,我们往往是采用脚本自动备份,下面演示一下备份相关问题

1.创建备份脚本,指定备份的数据库,用户密码等等

  1. [root@client100 ~]# vim backup.sh  
  2. # 备份脚本如下:  
  3.   
  4. #! /bin/bash  
  5.   
  6. # 进入mysqldump命令目录  
  7. cd /usr/bin/  
  8.   
  9. # 设置备份的时间,备份信息存放文件,备份路径,压缩路径,备份的用户,密码,主机,端口,数据库  
  10. DD=`date +%y-%m-%d==%H:%M:%S`  
  11. LOGFILE=/var/lib/mysql/mysqlbackup.log  
  12. backup_dir=/var/lib/mysql/dbbackup/  
  13. zip_dir=/var/lib/mysql/zipdir/  
  14. dbusername=backup  
  15. dbpassword=kongzhong  
  16. host=127.0.0.1  
  17. port=3306  
  18. # port2=3307  
  19. database1=login  
  20. # database2=  
  21. # database3=  
  22.   
  23. # 指定生成备份的文件名,压缩后的文件名  
  24. DumpFile=”$database1″$(date +%y%m%d).dump  
  25. NewFile=”$database1″$(date +%y%m%d).tgz  
  26.   
  27. # 查看备份的目录是否存在,不存在建立,并修改为mysql权限,并将相应输出信息写入日志文件  
  28. echo “check directory…” >> $LOGFILE  
  29. if [ ! -d $backup_dir ] ;then  
  30.   mkdir -p $backup_dir  
  31.   chown mysql:mysql $backup_dir  
  32. fi  
  33. echo $DD ” backup start…” >> $LOGFILE  
  34. echo $DD >>$LOGFILE  
  35. echo “backup “$database1″ …” >> $LOGFILE  
  36.   
  37. # 备份数据库  
  38. ./mysqldump -h$host -P$port -u$dbusername -p$dbpassword  $database1 > $backup_dir$DumpFile  
  39.   
  40. # 进入数据备份目录,压缩备份的文件,压缩完后删除dump文件  
  41. cd $backup_dir  
  42. tar czvf $NewFile $DumpFile >> $LOGFILE 2>&1  
  43. rm -rf $DumpFile  
  44.   
  45. # 判断压缩存放目录是否存在,不存在,建立,修改权限,并将压缩过的备份文件移送到压缩目录  
  46. echo “moving zipfiles …” >> $LOGFILE  
  47. cd $backup_dir  
  48. if [ ! -d $zip_dir ] ;then  
  49.   mkdir -p $zip_dir  
  50.   chown mysql:mysql $zip_dir  
  51. fi  
  52.  mv *.tgz  $zip_dir  
  53.   
  54. # 删除3天前的备份  
  55. #remove before 3 days  
  56. echo “remove before 3 days…” >> $LOGFILE  
  57. find $zip_dir –type f -mtime +3 –exec rm -f {} \;  
  58. echo “remove before 3 days OK” >>$LOGFILE  
  59.   
  60. echo “backup over” >> $LOGFILE  

2.给备份文件执行的权限

[root@client100 ~]# chmod +x backup.sh

3.先执行脚本测试,是否报错

[root@client100 ~]# ./backup.sh

4.如果测试正常,切换到mysql用户目录下,建立计划任务(假设每天凌晨3点备份)

[root@client100 ~]# su – mysql

# 下面就是建立计划任务(分 时 日 月 周 执行脚本的路径文件名)

[mysql@client100 ~]#crontab -e

0 3 * * * ./tmp/backup.sh

# 如果计划任务建好后,使用下面命令可以看到

[mysql@client100 ~]#crontab -l

5.现在备份计划就做好了,下面就可以正式测试了[如果备份有错误,可以查看刚才设置的备份日志,看输出信息排错]

 

mysql-cluster 初识

      最近,对mysql-cluster进行初步了解,发现和oracle提供的RAC有一定的相似之处,但区别又很大,下面主要是mysql-cluster的搭建,至于对其的深入了解,留着以后工作需要用到时,再进行深入,现在先了解和掌握其基本的思路
      这篇文章写的比较乱,不建议参考,仅做个人记录之用,
      推荐参考博客:叶金荣:http://imysql.cn/
     1.配置环境说明和官方拓扑图
官方拓扑图:

mysql-cluster

数据节点(ndb):

    192.168.1.119
    192.168.1.120
    192.168.1.121
    192.168.1.122
SQL节点:
    192.168.1.123
    192.168.1.124
    192.168.1.125
管理节点:
    192.168.1.118
系统:red hat linux 6(2.6.32)
       2.修改所有主机的host文件,hosts文件内容如下[所有机器都需要配置]
  1. [root@client119 ~]# vim /etc/hosts  
  2. 192.168.1.118 client118.kongzhong.com  client118  
  3. 192.168.1.119 client119.kongzhong.com  client119  
  4. 192.168.1.120 client120.kongzhong.com  client120  
  5. 192.168.1.121 client121.kongzhong.com  client121  
  6. 192.168.1.122 client122.kongzhong.com  client122  
  7. 192.168.1.123 client123.kongzhong.com  client123  
  8. 192.168.1.124 client124.kongzhong.com  client124  
  9. 192.168.1.125 client125.kongzhong.com  client125  
  10. 192.168.1.126 client126.kongzhong.com  client126  

3.mysql-cluster 管理节点配置:

(1).在管理节点[192.168.1.118]上建立一个存放cluster配置文件的目录

  1. [root@client118 ~]# mkdir /var/lib/mysql-cluster  
  2. [root@client118 ~]# cd /var/lib/mysql-cluster/  

(2).编写配置文件

  1. [root@client118 mysql-cluster]# vim configure.ini  
  2. [配置文件内容如下]  
  3. # [ndbd default]:表示每个数据节点的默认配置,在每个节点的[NDBD]中不用再写这些选项  
  4. [ndbd default]  
  5. # 每个数据节点的镜像数量(即复制成员的个数)  
  6. NoOfReplicas=2  
  7. # 为数据存储分配的内存  
  8. DataMemory=80M  
  9. # 为索引存储分配的内存  
  10. IndexMemory=18M  
  11.   
  12. [ndb_mgmd]  
  13. # 定义管理节点的ip地址或者主机名  
  14. hostname=192.168.1.118  
  15. #  管理节点数据(日志)目录  
  16. datadir=/var/lib/mysql-cluster  
  17.   
  18. # 定义数据节点的ip地址,数据存放目录  
  19. [ndbd]  
  20. hostname=192.168.1.122  
  21. datadir=/usr/local/mysql  
  22.   
  23. [ndbd]  
  24. hostname=192.168.1.119  
  25. datadir=/usr/local/mysql  
  26.   
  27. [ndbd]  
  28. hostname=192.168.1.120  
  29. datadir=/usr/local/mysql  
  30.   
  31. [ndbd]  
  32. hostname=192.168.1.121  
  33. datadir=/usr/local/mysql  
  34.   
  35. # 定义sql节点  
  36. [mysqld]  
  37. hostname=192.168.1.125  
  38.   
  39. [mysqld]  
  40. hostname=192.168.1.123  
  41.   
  42. [mysqld]  
  43. hostname=192.168.1.124  
  44.   
  45. # 留一个空的[mysqld],以备扩展用, 否则会出现Failed to allocate nodeid No free node id found for ndbd(NDB)错误  
  46. [mysqld]  
  47. [mysqld]  

(3).解压mysql-cluster压缩包

  1. [root@client118 ~]# tar -xf mysql-cluster-gpl-7.3.3-linux-glibc2.5-x86_64.tar.gz  
  2. [root@client118 ~]# cd mysql-cluster-gpl-7.3.3-linux-glibc2.5-x86_64  
  3. # 将管理节点用到的两个ndb_mgm*命令复制到/usr/local/bin/下  
  4. [root@client118 mysql-cluster-gpl-7.3.3-linux-glibc2.5-x86_64]# cp bin/ndb_mgm* /usr/local/bin/  
  5. [root@client118 mysql-cluster-gpl-7.3.3-linux-glibc2.5-x86_64]# cd /usr/local/bin/  
  6. # 将上述命令赋予执行权限  
  7. [root@client118 bin]# chmod +x ndb_mgm*  
  8. # 建立mysql目录  
  9. [root@client118 bin]# mkdir /usr/local/mysql  

4.配置数据节点和sql节点:

# 我在数据节点和sql节点都初始化了系统数据库,个人觉得数据节点可以不初始化系统数据库,大家可以这样试一下

(1).在每个sql节点和数据节点配置my.cnf

  1. [root@client123 ~]# vim /etc/my.cnf   
  2. [client]  
  3. socket=/usr/local/mysql/sock/mysql.sock  
  4. [mysqld]  
  5. ndbcluster  
  6. datadir=/usr/local/mysql  
  7. socket=/usr/local/mysql/sock/mysql.sock  
  8. port=3306  
  9. # 指定管理节点ip地址  
  10. ndb-connectstring=192.168.1.118  
  11. old_passwords=1  
  12. [mysql_cluster]  
  13. # 指定管理节点ip地址  
  14. ndb-connectstring=192.168.1.118  

(2).在每个sql节点创建mysql用户和组[可以仅在sql节点执行建立mysql用户,数据节点可建可不建]

  1. [root@client120 ~]# groupadd mysql  
  2. [root@client120 ~]# useradd -g mysql mysql  
  3. # 建立mysql目录  
  4. [root@client123 ~]# mkdir /usr/local/mysql  
  5. [root@client123 ~]# mkdir /usr/local/mysql/sock  

(3).在sql节点和数据节点都执行如下操作[数据节点如果在/usr/local没有mysql目录,建立此目录]

  1. [root@client123 ~]# tar -xf mysql-cluster-gpl-7.3.3-linux-glibc2.5-x86_64.tar.gz -C /usr/local/  
  2. [root@client123 ~]# cd /usr/local/mysql-cluster-gpl-7.3.3-linux-glibc2.5-x86_64  
  3. # 将解压的内容移动到 /usr/local/mysql目录下  
  4. [root@client124 mysql-cluster-gpl-7.3.3-linux-glibc2.5-x86_64]# mv ./* ../mysql  

(4).在sql节点初始化系统数据库,并修改相应目录权限和开机启动

  1. # 初始化系统数据库  
  2. [root@client124 mysql]# scripts/mysql_install_db –user=mysql –basedir=/usr/local/mysql –datadir=/usr/local/mysql   
  3. [root@client123 mysql]# chown -R mysql.mysql /usr/local/mysql/data  
  4. [root@client123 mysql]# chown -R mysql.mysql /usr/local/mysql/sock  
  5. [root@client123 mysql]# chown -R mysql .  
  6. [root@client123 mysql]# cp support-files/mysql.server /etc/init.d/mysqld  
  7. [root@client123 mysql]# chmod +x /etc/init.d/mysqld  
  8. [root@client123 mysql]# chkconfig –add mysqld   

5.cluster环境的启动

注意启动顺序:首先是管理节点,然后是NDBD节点,最后是SQL节点。

关闭顺序:先关闭sql节点,再关闭管理节点[ndb_mgm> shutdown]

(1).管理节点启动

  1. [root@client118 ~]#  ndb_mgmd -f /var/lib/mysql-cluster/config.ini  
  2. # 启用ndb_mgm来监听客户端,如下:  
  3. [root@client118 ~]#  ndb_mgm  
  4. # 输入show,查看集群状况  
  5. ndb_mgm> show  

(2).启动数据(ndb)节点

  1. # 首次启动,则需要添加–initial参数,以便进行NDB节点的初始化工作。  
  2. # 在以后的启动过程中,则是不能添加该参数的,否则ndbd程序会清除在之前建立的所有用于恢复的数据文件和日志文件[在备份、恢复或配置变化后重启时除外]  
  3. [root@client119 ~]#  /usr/local/mysql/bin/ndbd –initial  
  4. 如果不是首次启动,则执行下面的命令。  
  5. [root@client119 ~]#  /usr/local/mysql/bin/ndbd  

(3).sql节点启动

  1. # sql节点可以执行如下命令  
  2. [root@client123 ~]# /usr/local/mysql/bin/mysqld_safe –user=mysql &  
  3. # 如果将mysql的启动脚本已经复制到/etc/init.d下,可以执行如下:  
  4. [root@client123 ~]# /etc/init.d/mysqld start  

(4).现在再到管理节点,使用show命令看,是不是数据节点和sql节点都连上了

  1. ndb_mgm> show  
  2. Cluster Configuration  
  3. ———————  
  4. [ndbd(NDB)]     4 node(s)  
  5. id=2    @192.168.1.122  (mysql-5.6.14 ndb-7.3.3, Nodegroup: 0, *)  
  6. id=3    @192.168.1.119  (mysql-5.6.14 ndb-7.3.3, Nodegroup: 0)  
  7. id=4    @192.168.1.120  (mysql-5.6.14 ndb-7.3.3, Nodegroup: 1)  
  8. id=5    @192.168.1.121  (mysql-5.6.14 ndb-7.3.3, Nodegroup: 1)  
  9.   
  10. [ndb_mgmd(MGM)] 1 node(s)  
  11. id=1    @192.168.1.118  (mysql-5.6.14 ndb-7.3.3)  
  12.   
  13. [mysqld(API)]   5 node(s)  
  14. id=6    @192.168.1.125  (mysql-5.6.14 ndb-7.3.3)  
  15. id=7    @192.168.1.123  (mysql-5.6.14 ndb-7.3.3)  
  16. id=8    @192.168.1.124  (mysql-5.6.14 ndb-7.3.3)  
  17. id=9 (not connected, accepting connect from any host)  
  18. id=10 (not connected, accepting connect from any host)  

6.测试

(1).在任意sql节点创建测试数据

  1. # 为了让表在cluster中正常复制,创建一个表必须使用ndbcluster引擎(engine=ndb Or engine=ndbcluster)方法如下:  
  2. [root@client123 ~]# mysql  
  3. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  4. Your MySQL connection id is 2  
  5. Server version: 5.6.14-ndb-7.3.3-cluster-gpl MySQL Cluster Community Server (GPL)  
  6. Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.  
  7. Oracle is a registered trademark of Oracle Corporation and/or its  
  8. affiliates. Other names may be trademarks of their respective  
  9. owners.  
  10. Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.  
  11. mysql> create database xcg;  
  12. mysql>use xcg  
  13. mysql>create table teacher(t_id int) engine=ndb;  
  14. # 如果是一个已经存在的表,用alter table修改表的引擎。  
  15. mysql>alter table student engine=ndb;  
  16. # 插入一条数据:  
  17. mysql>insert into teacher values(133);  
  18.   
  19. #  然后用另外一个sql节点登陆,查询数据,看是否能看到  
  20. mysql>select * from teacher;  
  21. # 两个节点数据保持一致,说明测试成功!  

(2).模拟某一个数据(ndb)节点节点宕掉

# 在任意一个数据节点上终止掉NDB进程,然后再分别通过SQL节点去访问teacher表,查看是否可以正常访问,数据是否一致。

# 这里就不演示了,各位自行测试,ndb进程使用kill -9 杀掉进程

(3).模拟sql节点宕掉,原理同上,不演示

注意:

(1).在测试过程中,遇到ndb节点莫名重启,有点纳闷,待解!

(2).每次修改config.ini文件,重启ndb_mgmd时,需要删除mysql-cluster文件下的ndb_1_config.bin.1文件,
因为他默认调用此文件

(3).mysql-cluster主要配置选项:管理节点配置configure.ini,sql和数据节点配置/etc/my.cnf

敢于向生活挑战,追逐梦想,勇往前行

life     在生活中会不断的出现选择,每次的选择不管对与错,都是自己选择的,可在路途中,我们不断的选择是否会偏离我们自己的理想?我一直在思考这个问题。

选择无非就是得与失,对与错,可有多少是长远的呢?当现实步步紧逼,逼得我们现在时常用2B青年、屌丝来形容自己的时候。哪些当初的豪言壮语,勇气与魄力,在这个社会的熔炉里还剩下多少?最可怕的是我们离自己的理想渐行渐远,不敢再去追逐了,我们也一心想着买房成家立业,然后努力还房贷,我不知道那样之后还能拿出多少胆量去践行当初的诺言,可怕之极。

我想我们都应该做一个敢向生活挑战的人,不去在意那些一时的光环与别人的赞美,应该心中坚持自己的理想不动摇,千磨万击还坚劲,任尔东西南北风,用三五年甚至十年做我们认为对的事情,成就一定不会在别人之下。

工作以来,曾经多少次,我动摇过自己的理想,想去平平淡淡的生活;曾经多少次,我开始怀疑自己的能力,想逃避哪些不愿面对的困难与挫折;曾经多少次,我在黑夜里徘徊,想回到爸妈身边,让那漂泊的心感到温暖。可我还这么年轻,我那肯甘心就 这样在短暂的生命岁月里始终如一,更不想自己的在未来的选择中偏离了自己心中的理想,所以我要做一个敢向生活挑战的人。

在大学毕业之前的很多很多选择,都在不经意间就过去了。上大学,选学校和专业,完全是凭一时兴起。选择交朋友都是凭对这个人的直觉而定,选择做一件事情,看当时的心情等等不一而足。甚至在找工作时,面对压力,就想随便找个工作,有两三千 就行了,管它是干啥的,可当我因为这种心态选择签完工作后,我就后悔了。我在想我大学确立的理想离我的选择偏离了很远,当现在的工作出现时,我毅然决定选 择了,虽然走了弯路,也为此付出了代价,可也让我意识到,我的满腔热血会纠正我走在一条正确的道路上。当工作之后,身边的人都工作了,由于不同的原因,大家走的路不同,有安稳工作的,有买房准备结婚的,有果断裸婚的,这样身边就有很多声音,有了很多对比,同样我也会去羡慕。我在想我要是买房了,然后找个对象结婚,会不会也是成为别人此刻羡慕的对象。但这却要面对后续得压力,开始照顾家庭,养育子女,去还房贷,成了生活的全部,我都不敢保证自己在这样的压力 下还能不能坚决的去追逐自己的理想。虽然这是一种想象,可我却很害怕,这不是按部就班的生活下去了吗?这不是向生活低头了吗?男人靠征服世界来征服女人,谁不想豪气冲天,无尽挥洒。那只有做一个敢向生活挑战的人,用行动来证明,不管成功与否,我相信那酣畅淋漓的过程定然让人热血沸腾,无悔一生。

我做出了选择,不屈服于生活,宁可漂泊,抛弃短暂的得失,也定当沿着我理想的路走下去。不知道哪位高人说:“自己选择的路,就是爬也要走完。”虽然蛊惑人心,却不失我们的信念。也忘却了不知道谁说的:“走自己的路,让别人去说吧。”让我 明白了,前进的路上肯定有人觉得我比你过得好,家庭、事业都有了,可我追求的不单单是这些,就像当初我“幼稚”的想“华山我都能征服,那么身边还有我不能征服的高山么?当然我说的“幼稚”是因为华山有很多人都爬过。我想不甘于平庸的人,敢于向生活挑战的人,加之奋进的双手,一定是可以成功的。我们以30岁为一个节点,如今的选择基本就能预测30岁的自己可能到达一个什么样的高度。30而立,是一个男人真正成熟的开端,以前都是万仗高楼的基石,打得牢不牢靠,35岁,40岁时就非常明显了。我一直相信,人无远虑必有近忧,着眼于未来,就会发现,现在的事情大多是一堆琐事,不能羁绊前进的脚步和蒙住了智慧的双眼。

敢于做一个向生活挑战的人,会是痛并快乐着,那些和我一样做一个敢向生活挑战的人,我们都坚持把自己的理想进行到底,让我们在孤独的道路上并肩前行。

 

基于amoeba+keepalived+mmm实现mysql读写分离高可用架构

       在上一篇已经通过mysql-mmm实现对mysql数据库的动态监控,这一篇我们将结合amoeba实现对数据库访问的读写分离,通过keepalived来实现amoeba的高可用[keepalived用于监控主机心跳,软件是否宕掉无法监测,我们默认如果出问题就是amoeba的主机崩溃]
一、本次环境拓扑图如下:

amoeba+mmm+keepalived

二、环境描述
   系统:red hat linux 6(2.6.32)
   数据库:mysql 5.1.61(这里直接使用rpm包安装,也不使用最新版本数据库)
   MMM:mysql-mmm  2.2.21
   DB server地址分配:
          192.168.1.100(master)
          192.168.1.101(master)
          192.168.1.102(slave)
          192.168.1.103(slave)
   MMM地址:
          192.168.1.104(monitor)
   虚拟IP地址(vip):
          192.168.1.12(write)
          192.168.1.13(read)
          192.168.1.14(read)
          192.168.1.15(read)
  amoeba1:192.168.1.112
  amoeba1:192.168.1.113
  amoeba vip:192.168.1.17(对外的ip地址)
       本次环境软件下载:http://www.kuaipan.cn/file/id_119710994921422893.htm
       我们这里的配置是基于上一篇的环境,也就是说mysql-mmm和mysql的主从复制都配置好了,下面主要描述amoeba和keepalived
三、配置演示:
      Keepalived简介:Keepalived是Linux下面实现VRRP 备份路由的高可靠性运行件,基于Keepalived设计的服务模式能够真正做到主服务器和备份服务器故障时IP瞬间无缝交接,从而提高系统的可用性
      1.将需要的包传送到服务器并解压[我这里默认安装包已经上传到服务器家目录]
  1. # 在192.168.1.112/192.168.1.113上分别解压如下几个包  
  2. [root@client112 ~]# tar -xf keepalived-1.2.9.tar.gz  
  3. [root@client112 ~]# tar -xf jdk-7u15-linux-x64.tar.gz -C /usr/local/  
  4. # 在192.168.1.113  
  5. [root@client113 ~]# tar -xf keepalived-1.2.9.tar.gz  
  6. [root@client113 ~]# tar -xf jdk-7u15-linux-x64.tar.gz -C /usr/local/  

2.分别到192.168.1.112/192.168.1.113上配置java环境[这里只演示在112上的操作,113上重复此操作即可]

  1. [root@client112 ~]# cd /usr/local/  
  2. [root@client112 local]# mkdir java  
  3. # 将解压出来的内容移到java目录  
  4. [root@client112 local]# mv jdk1.7.0_15/* java  
  5. # 设置java环境变量  
  6. [root@client112 local]# echo $JAVA_HOME  
  7. [root@client112 local]# vim /etc/profile  
  8. # 在末尾添加  
  9. export JAVA_HOME=/usr/local/java  
  10. export AMOEBA_HOME=/usr/local/amoeba  
  11. export PATH=$PATH:$AMOEBA_HOME/bin:$JAVA_HOME/bin:$JAVA_HOME/jre/bin  
  12. # 使变量生效  
  13. [root@centos local]# source /etc/profile  

3.分别到192.168.1.112/192.168.1.113上配置amoeba[这里只演示在112上的操作,113上重复此操作即可]

(1).配置amoeba中的dbServer.xml(后端mysql 服务器连接配置)

  1. # 建立相应amoeba目录  
  2. [root@client112 local]# mkdir /usr/local/amoeba  
  3. # 将压缩包解压到指定目录  
  4. [root@client112 local]# tar -xf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba  
  5. [root@client112 local]# cd /usr/local/amoeba/  
  6. [root@client112 local]# cd conf/  
  7. # 配置后端mysql 服务器连接[dbServer.xml]  
  8. [root@client112 conf]# vim dbServers.xml  
  9. …………………….(省略)  
  10.         <dbServer name=”abstractServer” abstractive=”true”>  
  11.                 <factoryConfig class=”com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory”>  
  12.                         <property name=”manager”>${defaultManager}</property>  
  13.                         <property name=”sendBufferSize”>64</property>  
  14.                         <property name=”receiveBufferSize”>128</property>  
  15. # 设置 mysql 数据库的端口  
  16.                         <!– mysql port –>  
  17.                         <property name=”port”>3306</property>  
  18. # 设置缺省的数据库,当连接amoeba时,操作表必须显式的指定数据库名,即采用dbname.tablename的方式,  
  19. # 不支持 use dbname指定缺省库,因为操作会调度到各个后端dbserver   
  20.                         <!– mysql schema –>  
  21.                         <property name=”schema”>kongzhong</property>  
  22.  # 设置amoeba连接后端数据库服务器的账号和密码,需在后端数据库器上创建该用户,并授权amoeba连接   
  23. # 此处需要特别注意:**** 密码默认是注释掉,需要去掉注释!!!  
  24.                         <!– mysql user –>  
  25.                         <property name=”user“>kongzhong</property>  
  26.                         <!–  mysql password –>  
  27.                         <property name=”password”>kongzhong</property>  
  28.                 </factoryConfig>  
  29.                 <poolConfig class=”com.meidusa.amoeba.net.poolable.PoolableObjectPool”>  
  30.  # 最大连接数[默认]  
  31.                         <property name=”maxActive”>500</property>  
  32.  # 最大空闲连接数[默认]   
  33.                         <property name=”maxIdle”>500</property>  
  34.                         <property name=”minIdle”>10</property>  
  35.                         <property name=”minEvictableIdleTimeMillis”>600000</property>  
  36.                         <property name=”timeBetweenEvictionRunsMillis”>600000</property>  
  37.                         <property name=”testOnBorrow”>true</property>  
  38.                         <property name=”testOnReturn”>true</property>  
  39.                         <property name=”testWhileIdle”>true</property>  
  40.                 </poolConfig>  
  41.         </dbServer>  
  42.  # 设置一个后端的dbServer,名为master ,这个可以随便取,但是为了明确其含义,最好给予特殊含义的单词   
  43. # 下面指定的数据库IP地址,为mmm提供给对外访问的虚拟IP地址  
  44.  <dbServer name=”master”  parent=”abstractServer”>  
  45. <factoryConfig>  
  46.  <!– mysql ip –>  
  47.  <property name=”ipAddress”>192.168.1.12</property>  
  48.  </factoryConfig>  
  49. </dbServer>  
  50.  <dbServer name=”slave1″  parent=”abstractServer”>  
  51. <factoryConfig>  
  52.  <!– mysql ip –>  
  53.  <property name=”ipAddress”>192.168.1.13</property>  
  54. </factoryConfig>  
  55. </dbServer>  
  56. <dbServer name=”slave2″  parent=”abstractServer”>  
  57. <factoryConfig>  
  58. <!– mysql ip –>  
  59. <property name=”ipAddress”>192.168.1.14</property>  
  60. </factoryConfig>  
  61. </dbServer>  
  62. <dbServer name=”slave3″  parent=”abstractServer”>  
  63. <factoryConfig>  
  64. <!– mysql ip –>  
  65. <property name=”ipAddress”>192.168.1.15</property>  
  66. </factoryConfig>  
  67. </dbServer>  
  68. <dbServer name=”slave4″  parent=”abstractServer”>  
  69. <factoryConfig>  
  70. <!– mysql ip –>  
  71. <property name=”ipAddress”>192.168.1.16</property>  
  72. </factoryConfig>  
  73. </dbServer>  
  74.   
  75. # 指定一个虚拟的dbServer,将上面定义的dbserver加入这个虚拟的dbserver,相当于组成一个组[这里我们将读的数据库组成一个组]  
  76. # 这里 需要将 name=”mul…” 改成自己想要取的名字,这个名字也需要有含义,后面会用到  
  77.         <dbServer name=”virtualslave” virtual=”true”>  
  78.                 <poolConfig class=”com.meidusa.amoeba.server.MultipleServerPool”>  
  79.                         <!– Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA–>  
  80. # 选择调度算法 1 是轮询 2 是权重 3 是HA 这里选择1 轮询  
  81.                         <property name=”loadbalance”>1</property>  
  82.                         <!– Separated by commas,such as: server1,server2,server1 –>  
  83. # 负载均衡,slave1,slave2当成2个服务器进行调度,这模拟量加权的调度算法。  
  84. # 注意这里使用的dbserver必须是已经定义了的,可以写多个,如slave1,slave2  
  85.                         <property name=”poolNames”>slave1,slave2,slave3,slave4</property>  
  86.                 </poolConfig>  
  87.         </dbServer>  
  88. </amoeba:dbServers>  

(2).配置 Amoeba 监听端口[amoeba.xml]

  1. [root@client112 conf]# vim amoeba.xml  
  2. …………………….(省略)  
  3.         <proxy>  
  4.                 <!– service class must implements com.meidusa.amoeba.service.Service –>  
  5.                 <service name=”Amoeba for Mysql” class=”com.meidusa.amoeba.net.ServerableConnectionManager”>  
  6.                         <!– port –>  
  7.  # 设置amoeba监听的端口(这里如果默认,后面测试需要指定端口,就是这里的端口)  
  8.                         <property name=”port”>3306</property>  
  9.                         <!– bind ipAddress –>  
  10.                         <!–  
  11.  # 设置监听的接口,如果不设置,则监听所有的IP[选择默认]   
  12.                         <property name=”ipAddress”>127.0.0.1</property>  
  13.                          –>  
  14. …………………….(省略)  
  15.                         <property name=”authenticator”>  
  16.                                 <bean class=”com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator”>  
  17. # 提供客户端连接amoeba时需要使用这里设定的账号 (这里的账号密码和amoeba连接后端数据库服务器的密码无关)  
  18.                                         <property name=”user“>kongzhong123</property>  
  19. # 提供客户端连接amoeba时需要使用这里设定的密码  
  20.                                         <property name=”password”>kongzhong123</property>  
  21.                                         <property name=”filter“>  
  22.                                                 <bean class=”com.meidusa.amoeba.server.IPAccessController”>  
  23.                                                         <property name=”ipFile”>${amoeba.home}/conf/access_list.conf</property>  
  24.                                                 </bean>  
  25.                                         </property>  
  26.                                 </bean>  
  27.                         </property>  
  28.                 </service>  
  29. …………………….(省略)  
  30.         <queryRouter class=”com.meidusa.amoeba.mysql.parser.MysqlQueryRouter”>  
  31.                 <property name=”ruleLoader”>  
  32.                         <bean class=”com.meidusa.amoeba.route.TableRuleFileLoader”>  
  33.                                 <property name=”ruleFile”>${amoeba.home}/conf/rule.xml</property>  
  34.                                 <property name=”functionFile”>${amoeba.home}/conf/ruleFunctionMap.xml</property>  
  35.                         </bean>  
  36.                 </property>  
  37.                 <property name=”sqlFunctionFile”>${amoeba.home}/conf/functionMap.xml</property>  
  38.                 <property name=”LRUMapSize”>1500</property>  
  39.                 <property name=”defaultPool”>master</property>  
  40.                 <!–                 –>  
  41. # 把默认注释掉的读写分离选项,把注释去掉并readpool修改成virtualslave(这个名字,我们前面在dbServer.xml里设置一个读数据库组,这里是作为只读池)   
  42.                 <property name=”writePool”>master</property>  
  43.                 <property name=”readPool”>virtualslave</property>  
  44.                 <property name=”needParse”>true</property>  
  45.         </queryRouter>  

(3).配置amoeba及JAVA的环境变量[这个上面配置java时配置过,如果没有配置参照下面]

  1. [root@client112 local]# vim /etc/profile  
  2. # 在末尾添加  
  3. export JAVA_HOME=/usr/local/java   
  4. export AMOEBA_HOME=/usr/local/amoeba   
  5. export PATH=$PATH:$AMOEBA_HOME/bin:$JAVA_HOME/bin:$JAVA_HOME/jre/bin    
  6. # 使变量生效  
  7. [root@centos local]# source /etc/profile  

(4)登陆数据库授权相应用户权限

  1. #  登陆任意一个主master,授权amoeba用到登陆用户(kongzhong需要授权,kongzhong123用于给前端登陆的不需要授权)  
  2. mysql> create database kongzhong;  
  3. mysql> grant all privileges on kongzhong.* to ‘kongzhong’@’192.168.1.%’ identified by ‘kongzhong’;  
  4. mysql> flush privileges;  

(5).启动amoeba测试

  1. # 如果确认能够正常启动,就加>>/dev/null 否则还是看一下提示信息  
  2. [root@centos conf]# amoeba start & >>/dev/null   
  3. # 检测启动情况  
  4. [root@centos conf]# netstat -tulnp |grep java  
  5. # 停止amoeba测试指令是否可用  
  6. [root@centos conf]# amoeba stop  

(6).利用amoeba登陆测试[任何一台具有mysql客户端,出现以下提示即为正常]

  1. [root@client100 ~]# mysql -h192.168.1.112 -ukongzhong123 -pkongzhong123  
  2. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  3. Your MySQL connection id is 1201340161  
  4. Server version: 5.1.45-mysql-amoeba-proxy-2.2.0 Source distribution  
  5.   
  6. Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.  
  7.   
  8. Oracle is a registered trademark of Oracle Corporation and/or its  
  9. affiliates. Other names may be trademarks of their respective  
  10. owners.  
  11.   
  12. Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.  
  13.   
  14. mysql> show databases;  
  15. +——————–+  
  16. | Database           |  
  17. +——————–+  
  18. | information_schema |  
  19. | kongzhong          |  
  20. | test               |  
  21. +——————–+  

(7).在192.168.1.113配置amoeba,这里就不再延迟,重复上面配置amoeba的操作

4.安装和配置keepalived

  1. # keepalived需要openssl依赖包  
  2. [root@client112 ~]# yum -y install openssl* gcc make  
  3. # 建立keepalived安装目录  
  4. [root@client112 ~]# mkdir /usr/local/keepalived  
  5. [root@client112 ~]# cd keepalived-1.2.9  
  6. [root@client112 keepalived-1.2.9]# ./configure –prefix=/usr/local/keepalived  
  7. [root@client112 keepalived-1.2.9]# make  
  8. [root@client112 keepalived-1.2.9]# make install  
  9. # 复制相应文件到指定目录  
  10. [root@client112 keepalived-1.2.9]# cp /usr/local/keepalived/sbin/keepalived /usr/sbin/  
  11. [root@client112 keepalived-1.2.9]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/  
  12. [root@client112 keepalived-1.2.9]# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/  
  13. [root@client112 keepalived-1.2.9]# mkdir /etc/keepalived  
  14. [root@client112 keepalived-1.2.9]# cd /etc/keepalived/  
  15.   
  16. # 以上的关于keepalived操作,请重复在192.168.1.113操作一遍  
  17. # 以下操作,根据提示操作  
  18. # 编辑配置文件[192.168.1.112上的配置文件]  
  19. [root@client112 keepalived]# vim keepalived.conf  
  20. bal_defs {  
  21. notification_email  
  22. {  
  23. # 设置报警邮件地址,每行一个  
  24. # 需开启本机sendmail服务[这里可以暂时忽略]  
  25. cloud_data@163.com  
  26. }  
  27. #设置邮件发送地址  
  28. notification_email_from cloud_data@163.com  
  29. #设置smtp server 地址  
  30. smtp_server 127.0.0.1  
  31. #设置连接 smtp server超时时间  
  32. smtp_connect_timeout 30  
  33. #运行Keepalived服务器的一个标志,邮件主题中显示  
  34. router_id client112  
  35. }  
  36. # vrrp实例定义部分  
  37. vrrp_instance VI_1 {  
  38. # 指定keepalived的角色,MASTER表示此主机是主服务器  
  39. # BACKUP表示是备用服务器  
  40. state MASTER  
  41. # 指定HA监测网络的接口  
  42. interface eth0  
  43. # 虚拟路由标志,同一个vrrp实例使用一个唯一标志  
  44. # 即同一个vrrp_instance下,MASTER和BACKUP一致  
  45. virtual_router_id 51  
  46. # 优先级,数字越大优先级越高,MASTER必须大于BACKUP  
  47. priority 100  
  48. # MASTER和BACKUP同步检查间隔,秒  
  49. advert_int 1  
  50. smtp_alert  
  51. # 设定验证类型和密码  
  52. authentication {  
  53. # 验证类型,PASS和HA  
  54. auth_type PASS  
  55. # 验证密码,MASTER和BACKUP密码相同才能进行通信  
  56. auth_pass kongzhong  
  57. }  
  58. # 虚拟ip地址  
  59. virtual_ipaddress  
  60. {  
  61. 192.168.1.17  
  62.   
  63. }  
  64. }  
  65.   
  66. # 编辑配置文件[192.168.1.113上的配置文件]  
  67. [root@client113 keepalived]# vim keepalived.conf  
  68. bal_defs {  
  69.   
  70. notification_email  
  71. {  
  72. cloud_data@163.com  
  73. }  
  74. notification_email_from cloud_data@163.com  
  75. smtp_server 127.0.0.1  
  76. smtp_connect_timeout 30  
  77. router_id client113  
  78. }  
  79.   
  80. vrrp_instance VI_1 {  
  81. # 这里和192.168.1.112上不同,修改为BACKUP  
  82. state BACKUP  
  83. interface eth0  
  84. virtual_router_id 51  
  85. # 这里和192.168.1.112上不同,修改为80  
  86. priority 80  
  87. advert_int 1  
  88. smtp_alert  
  89. authentication {  
  90. # 这里需要和192.168.1.112上的一样,不然,无法切换的  
  91. auth_type PASS  
  92. auth_pass kongzhong  
  93. }  
  94. virtual_ipaddress  
  95. {  
  96. 192.168.1.17  
  97. }  
  98. }  
  99.   
  100. # 分别在192.168.1.112和192.168.1.113上启动keepalived  
  101. [root@client112 keepalived]# /etc/init.d/keepalived start  
  102. Starting keepalived: [ OK ]  
  103. # 检查虚拟ip是否绑定网卡[这里ip默认会在优先级比较高的机器上,就是刚才设置的100和80]  
  104. [root@client112 keepalived]# ip add | grep 192.168.1.17  
  105. inet 192.168.1.17/32 scope global eth0  
  106. # 192.168.1.113上启动keepalived  
  107. [root@client113 keepalived]# /etc/init.d/keepalived start  
  108. Starting keepalived: [ OK ]  
  109. # 113上如果需要看到ip需要关闭keepalived,也就是模拟112宕机  
  110. [root@client113 keepalived]# ip add | grep 192.168.1.17  
  111. # 停掉192.168.1.112的keepalived,看看虚拟IP192.168.1.17会不会自动切换到192.168.1.113上  

5.现在就可以测试了:

简单测试:

(1).使用amoeba的真实ip登陆

  1. [root@client100 ~]# mysql -h192.168.1.112 -ukongzhong123 -pkongzhong123  
  2. [root@client100 ~]# mysql -h192.168.1.113 -ukongzhong123 -pkongzhong123  

(2).使用keepalived提供的虚拟ip访问

  1. [root@client100 ~]# mysql -h192.168.1.17 -ukongzhong123 -pkongzhong123  

(3).模拟宕掉一台amoeba[即关闭keepalived],看还能否使用keepalived提供的虚拟ip访问

  1. # 这时虚拟ip应该切换到另外一台好的amoeba上  
  2. [root@client100 ~]# mysql -h192.168.1.17 -ukongzhong123 -pkongzhong123  

基于mysql-mmm实现对mysql replication进行监控和故障迁移

一、mysql-mmm简述:
       mysq-mmm英译:MYSQL-MMM(Mysql Master-Master replication manager for Mysql)是一套基于perl编写的脚本程序(这也是我们配置时需要安装perl相关的依赖包),用来对 mysql replication 进行监控和故障迁移,并能管理 mysql Master-Master 复制的配置(同一时间只有一个节点是可写的,在DB server宕掉后,会自动帮你重新配置主从),附带的工具套件可以实现多个 slaves 的 read 负载均衡,因此你可以使用这个工具移除一组服务器中复制延迟较高的服务器的虚拟 IP,它还可以备份数据,两节点之间再同步等等。
二、mysql-mmm命令的组成部分及原理,相关用户简介[基于c/s架构,就是说代理端需要配置agent,监管端需要配置monitor]:
1.命令构成:
       mmm_mond :监控进程,负责所有的监控工作,决定和处理所有节点角色活动。此脚本需要在监管机上运行。
       mmm_agentd :运行在每个 mysql 服务器上的代理进程,完成监控的探针工作和执行简单的远端服务设置 。此脚本需要在被监管机上运行。
       mmm_control :一个简单的脚本,提供管理 mmm_mond 进程的命令
2.mysql-mmm的原理:
       mysql-mmm 的监管端会提供多个虚拟 IP(VIP),包括一个可写 VIP,多个可读VIP,通过监管的管理,这些 IP 会绑定在可用 mysql 之上,当某一台 mysql 宕机时,监管机会将 VIP 迁移至其他 mysql。在整个监管过程中,需要在 mysql 中添加相关授权用户,以便让 mysql 可以支持监理机的维护。授权的用户包括一个 mmm_monitor 用户和一个 mmm_agent 用户。
3.相关用户简介:
      monitor user(这里使用:mmm_monitor):mmm监控用于对mysql服务器进程健康检查,需要具有 REPLICATION CLIENT
      agent user(这里使用:mmm_agent):mmm代理用来更改只读模式,复制的主服务器等等,需要具有 SUPER, REPLICATION CLIENT, PROCESS
      relication user(这里使用:slave):用于复制,需要具有 REPLICATION SLAVE
4.官方配置文档:
      mysql-mmm官方文档:http://mysql-mmm.org/mmm2:guide
三、本次测试环境拓扑图:

mysql-mmm

四、mysql-mmm配置实例:
1.测试环境:
系统:red hat linux 6(2.6.32)
数据库:mysql 5.1.61(这里直接使用rpm包安装,也不使用最新版本数据库)
MMM:mysql-mmm 2.2.21
DB server地址分配:
      192.168.1.100(master)
     192.168.1.101(master)
     192.168.1.102(slave)
     192.168.1.103(slave)
MMM地址:
     192.168.1.104(monitor)
虚拟IP地址(vip):
     192.168.1.12(write)
     192.168.1.13(read)
     192.168.1.14(read)
     192.168.1.15(read)

2.在DB server机器上安装、配置mysql数据库

  1. [root@client100 ~]# yum -y install mysql mysql-server
  2. [root@client101 ~]# yum -y install mysql mysql-server
  3. [root@client102 ~]# yum -y install mysql mysql-server
  4. [root@client103 ~]# yum -y install mysql mysql-server
  5. # 设置1台DB server(192.168.1.100)的登陆密码[其他机器使用备份恢复即可]
  6. [root@client100 ~]# mysqladmin -uroot password ‘kongzhong’
  7. # 修改192.168.1.100数据库配置文件
  8. [root@client100 ~]# vim /etc/my.cnf
  9. # 添加或修改如下参数
  10. max_connections=1400
  11. binlog-format=’row’
  12. server_id= 100
  13. log_bin= /var/lib/mysql/mysql-100-bin.log
  14. log_bin_index= /var/lib/mysql/mysql-bin.log.index
  15. relay_log= /var/lib/mysql/mysql-relay-bin
  16. relay_log_index= /var/lib/mysql/mysql-relay-bin.index
  17. expire_logs_days= 10
  18. max_binlog_size= 100M
  19. log_slave_updates= 1
  20. sync-binlog=1
  21. auto_increment_increment=2
  22. auto_increment_offset=1
  23. # skip-name-resolve 这个参数可以选配,如果不使用,则host配置文件必须有所有dbserver对应解析关系
  24. skip-name-resolve
  25. # 修改192.168.1.101数据库配置文件
  26. [root@client101 ~]# vim /etc/my.cnf
  27. max_connections=1400
  28. binlog-format=’row’
  29. server_id= 101
  30. log_bin= /var/lib/mysql/mysql-101-bin.log
  31. log_bin_index= /var/lib/mysql/mysql-bin.log.index
  32. relay_log= /var/lib/mysql/mysql-relay-bin
  33. relay_log_index= /var/lib/mysql/mysql-relay-bin.index
  34. expire_logs_days= 10
  35. max_binlog_size= 100M
  36. log_slave_updates= 1
  37. sync-binlog=1
  38. auto_increment_increment=2
  39. # 这个参数值和上面的值不一样
  40. auto_increment_offset=2
  41. skip-name-resolve
  42. # 修改192.168.1.102数据库配置文件
  43. [root@client102 ~]# vim /etc/my.cnf
  44. max_connections=1400
  45. server_id= 102
  46. log_bin= /var/lib/mysql/mysql-102-bin.log
  47. log_bin_index= /var/lib/mysql/mysql-bin.log.index
  48. relay_log= /var/lib/mysql/mysql-relay-bin
  49. relay_log_index= /var/lib/mysql/mysql-relay-bin.index
  50. log_slave_updates= 1
  51. # 修改192.168.1.103数据库配置文件
  52. [root@client103 ~]# vim /etc/my.cnf
  53. max_connections=1400
  54. server_id= 103
  55. log_bin= /var/lib/mysql/mysql-103-bin.log
  56. log_bin_index= /var/lib/mysql/mysql-bin.log.index
  57. relay_log= /var/lib/mysql/mysql-relay-bin
  58. relay_log_index= /var/lib/mysql/mysql-relay-bin.index
  59. log_slave_updates= 1
  60. # 启动所有DB server上的mysql数据库
  61. [root@client100 ~]# /etc/init.d/mysqld start
  62. [root@client101 ~]# /etc/init.d/mysqld start
  63. [root@client102 ~]# /etc/init.d/mysqld start
  64. [root@client103 ~]# /etc/init.d/mysqld start
  65. # 登陆192.168.1.100上的数据库,做授权操作(授权用户包括复制的用户,mmm需要的监控,代理用户等)
  66. mysql> grant replication slave on *.* to ‘slave’@’192.168.1.%’ identified by ‘kongzhong’;
  67. mysql> grant replication client on *.* to ‘mmm_monitor’@’192.168.1.%’ identified by ‘kongzhong’;
  68. mysql> grant replication client,process,super on *.* to ‘mmm_agent’@’192.168.1.%’ identified by ‘kongzhong’;
  69. mysql> flush privileges;
  70. # 备份192.168.1.100的数据,并传送到其他几台DB server上
  71. [root@client100 ~]# mysqldump -uroot -p –all-databases –lock-all-tables –flush-logs >/tmp/all.sql
  72. Enter password:
  73. [root@client100 ~]# scp /tmp/all.sql 192.168.1.101:/tmp/
  74. root@192.168.1.101’s password:
  75. all.sql 100% 495KB 495.3KB/s 00:00
  76. [root@client100 ~]# scp /tmp/all.sql 192.168.1.102:/tmp/
  77. root@192.168.1.102’s password:
  78. all.sql 100% 495KB 495.3KB/s 00:00
  79. [root@client100 ~]# scp /tmp/all.sql 192.168.1.103:/tmp/
  80. root@192.168.1.103’s password:
  81. all.sql 100% 495KB 495.3KB/s 00:00

3.配置DB server 的主从关系

(1).在192.168.1.101,192.168.1.102,192.168.1.103利用备份还原数据库,并重启数据库[这里不演示,大家都会]

(2).在192.168.1.100上查看当前日志文件的位置

  1. mysql> show master status;
  2. +———————-+———-+————–+——————+
  3. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
  4. +———————-+———-+————–+——————+
  5. | mysql-100-bin.000003 | 106 | | |
  6. +———————-+———-+————–+——————+
  7. 1 row in set (0.00 sec)

(3).在192.168.1.101,192.168.1.102,192.168.1.103配置与192.168.1.100的主从关系,语句如下:

  1. mysql> CHANGE MASTER TO master_host=’192.168.1.100′,
  2. -> master_port=3306,
  3. -> master_user=’slave’,
  4. -> master_password=’kongzhong’,
  5. -> master_log_file=’mysql-100-bin.000003′,
  6. -> master_log_pos=106;
  7. mysql> start slave;
  8. mysql> show slave start\G;
  9. # 配置完主从,查看下面两个参数的值是否为yes,根据提示排错
  10. Slave_IO_Running: Yes
  11. Slave_SQL_Running: Yes

(4).配置192.168.1.100与192.168.1.01互为主从

  1. # 在192.168.1.101上查看当前日志文件的位置
  2. mysql> show master status;
  3. +———————-+———-+————–+——————+
  4. | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
  5. +———————-+———-+————–+——————+
  6. | mysql-101-bin.000004 | 996936 | | |
  7. +———————-+———-+————–+——————+
  8. 1 row in set (0.00 sec)
  9. # 在192.168.1.100上,执行如下语句
  10. mysql>CHANGE MASTER TO master_host=’192.168.1.101′,
  11. -> master_port=3306,
  12. -> master_user=’slave’,
  13. -> master_password=’kongzhong’,
  14. -> master_log_file=’mysql-101-bin.000004′,
  15. -> master_log_pos=996936;
  16. mysql> start slave;
  17. mysql> show slave start\G;
  18. # 配置完主从,查看下面两个参数的值是否为yes,根据提示排错
  19. Slave_IO_Running: Yes
  20. Slave_SQL_Running: Yes
  21. # 以上配置完之后,大家可以在主DB server创建库来验证主从的有效性(这里不演示了)

4.在所有机器上安装如下软件:

  1. # 所有机器(包括dbserver和监控机器)都需安装[这里指演示在一台机器上安装]
  2. [root@client104 ~]# yum -y install libart_lgpl perl-Date-Manip perl-XML-DOM perl-XML-DOM-XPath perl-XML-Parser perl-XML-RegExp rrdtool perl-Class-Singleton perl perl-DBD-MySQL perl-Params-Validate perl-MailTools perl-Time-HiRes
  3. # 以下几个软件,本地光盘上是没有的,需要使用网络yum源[epel],我这里下载好了
  4. # 下载地址如下:http://www.kuaipan.cn/file/id_119710994921422892.htm
  5. [root@client104 ~]# yum -y install perl-Algorithm-Diff-1.1902-9.el6.noarch.rpm perl-IPC-Shareable-0.60-2.el6.rf.noarch.rpm perl-Log-Dispatch-2.26-1.el6.rf.noarch.rpm perl-Log-Log4perl-1.26-1.el6.rf.noarch.rpm perl-Net-ARP-1.0.6-2.1.el6.x86_64.rpm perl-Proc-Daemon-0.06-1.el6.noarch.rpm perl-Proc-ProcessTable-0.44-4.el6.x86_64.rpm rrdtool-perl-1.3.8-6.el6.x86_64.rpm
  6. # 数据库端需要安装
  7. [root@client101..3 ~]#yum -y install mysql-connector-odbc

5.在所有机器上安装mysql-mmm软件:

  1. # 安装mysql-mmm,可以使用epel提供的rpm包安装
  2. # 这里不使用rpm安装,软件都已共享,自行下载,在每台机器上安装mysql-mmm[这里仅演示在1台机器上mysql-mmm]
  3. [root@client104 ~]# tar -xf mysql-mmm-2.2.1.tar.gz
  4. [root@client104 ~]# cd mysql-mmm-2.2.1
  5. [root@client104 mysql-mmm-2.2.1]# make install
  6. # 配置mmm_common.conf,并传送到每台机器上对应目录[包括监控机]
  7. [root@client104 mysql-mmm-2.2.1]# vim /etc/mysql-mmm/mmm_common.conf
  8. active_master_role writer
  9. <host default>
  10. cluster_interface eth0
  11. pid_path /var/run/mmm_agentd.pid
  12. bin_path /usr/lib/mysql-mmm/
  13. # 用于主从复制的账户和密码
  14. replication_user slave
  15. replication_password kongzhong
  16. # 代理端的账户和密码[这些账户,上面都已做过授权,不清楚,可以回头看看]
  17. agent_user mmm_agent
  18. agent_password kongzhong
  19. </host>
  20. # 配置第一台DB server,这里的ip地址写真实数据库IP地址,模式为主dbserver
  21. <host db1>
  22. ip 192.168.1.100
  23. mode master
  24. peer db1
  25. </host>
  26. # 配置第二台DB server,模式为主dbserver
  27. <host db2>
  28. ip 192.168.1.101
  29. mode master
  30. peer db2
  31. </host>
  32. # 配置第三台DB server,模式为从dbserver
  33. <host db3>
  34. ip 192.168.1.102
  35. mode slave
  36. </host>
  37. # 配置第四台DB server,模式为从dbserver
  38. <host db4>
  39. ip 192.168.1.103
  40. mode slave
  41. </host>
  42. # 配置可写的DB server(即master dbserver),这里的ip为虚拟ip地址
  43. <role writer>
  44. hosts db1, db2
  45. ips 192.168.1.12
  46. mode exclusive
  47. </role>
  48. # 配置可读的DB server(可以是所有,也可以是部分),这里的ip为虚拟ip地址,模式为轮询,
  49. <role reader>
  50. hosts db1, db2, db3, db4
  51. ips 192.168.1.13, 192.168.1.14, 192.168.1.15,192.168.1.16
  52. mode balanced
  53. </role>
  54. # 上面的配置文件传送到各个主机
  55. [root@client104 mysql-mmm-2.2.1]# scp /etc/mysql-mmm/mmm_common.conf 192.168.1.101:/etc/mysql-mmm/mmm_common.conf
  56. [root@client104 mysql-mmm-2.2.1]# scp /etc/mysql-mmm/mmm_common.conf 192.168.1.102:/etc/mysql-mmm/mmm_common.conf
  57. [root@client104 mysql-mmm-2.2.1]# scp /etc/mysql-mmm/mmm_common.conf 192.168.1.103:/etc/mysql-mmm/mmm_common.conf
  58. [root@client104 mysql-mmm-2.2.1]# scp /etc/mysql-mmm/mmm_common.conf 192.168.1.100:/etc/mysql-mmm/mmm_common.conf

6.分别修改192.168.1.101,192.168.1.102,192.168.1.103,192.168.1.100的mmm_agent.conf文件,注意this 部分

  1. [root@client100 mysql-mmm-2.2.1]# vim /etc/mysql-mmm/mmm_agent.conf
  2. include mmm_common.conf
  3. this db1
  4. [root@client101 mysql-mmm-2.2.1]# vim /etc/mysql-mmm/mmm_agent.conf
  5. include mmm_common.conf
  6. this db2
  7. [root@client102 mysql-mmm-2.2.1]# vim /etc/mysql-mmm/mmm_agent.conf
  8. include mmm_common.conf
  9. this db3
  10. [root@client103 mysql-mmm-2.2.1]# vim /etc/mysql-mmm/mmm_agent.conf
  11. include mmm_common.conf
  12. this db4

7.修改监控端(192.168.1.104)的mmm_mon.conf文件[此文件仅监控端需要配置]

  1. [root@client104 mysql-mmm-2.2.1]# vim /etc/mysql-mmm/mmm_mon.conf
  2. include mmm_common.conf
  3. # 以下IP均为真实IP地址
  4. <monitor>
  5. ip 192.168.1.104
  6. pid_path /var/run/mmm_mond.pid
  7. bin_path /usr/lib/mysql-mmm/
  8. status_path /var/lib/misc/mmm_mond.status
  9. ping_ips 192.168.1.100, 192.168.1.101, 192.168.1.102, 192.168.1.103
  10. </monitor>
  11. # 监管的账号密码
  12. <host default>
  13. monitor_user mmm_monitor
  14. monitor_password kongzhong
  15. </host>
  16. debug 0

8.dbserver启动agent,监管端启动monitor

  1. [root@client100 ~]# /etc/init.d/mysql-mmm-agent start
  2. Daemon bin: ‘/usr/sbin/mmm_agentd’
  3. Daemon pid: ‘/var/run/mmm_agentd.pid’
  4. Starting MMM Agent daemon… Ok
  5. [root@client101 ~]# /etc/init.d/mysql-mmm-agent start
  6. Daemon bin: ‘/usr/sbin/mmm_agentd’
  7. Daemon pid: ‘/var/run/mmm_agentd.pid’
  8. Starting MMM Agent daemon… Ok
  9. [root@client102 ~]# /etc/init.d/mysql-mmm-agent start
  10. Daemon bin: ‘/usr/sbin/mmm_agentd’
  11. Daemon pid: ‘/var/run/mmm_agentd.pid’
  12. Starting MMM Agent daemon… Ok
  13. [root@client103 ~]# /etc/init.d/mysql-mmm-agent start
  14. Daemon bin: ‘/usr/sbin/mmm_agentd’
  15. Daemon pid: ‘/var/run/mmm_agentd.pid’
  16. Starting MMM Agent daemon… Ok
  17. # 监管端启动
  18. [root@client104 mysql-mmm-2.2.1]# /etc/init.d/mysql-mmm-monitor start
  19. Daemon bin: ‘/usr/sbin/mmm_mond’
  20. Daemon pid: ‘/var/run/mmm_mond.pid’
  21. Starting MMM Monitor daemon: Ok
  22. # 查看状态[第一次需要激活dbserver]
  23. [root@client104 ~]# mmm_control show
  24. db1(192.168.1.100) master/AWAITING_RECOVERY. Roles:
  25. db2(192.168.1.101) master/AWAITING_RECOVERY. Roles:
  26. db3(192.168.1.102) slave/AWAITING_RECOVERY. Roles:
  27. db4(192.168.1.103) slave/AWAITING_RECOVERY. Roles:
  28. # 激活所有dbserver
  29. [root@client104 ~]# mmm_control set_online db1
  30. [root@client104 ~]# mmm_control set_online db2
  31. [root@client104 ~]# mmm_control set_online db3
  32. [root@client104 ~]# mmm_control set_online db4
  33. # 再次查看
  34. [root@client104 ~]# mmm_control show
  35. db1(192.168.1.100) master/ONLINE. Roles: reader(192.168.1.14)
  36. db2(192.168.1.101) master/ONLINE. Roles: reader(192.168.1.13), writer(192.168.1.12)
  37. db3(192.168.1.102) slave/ONLINE. Roles: reader(192.168.1.16)
  38. db4(192.168.1.103) slave/ONLINE. Roles: reader(192.168.1.15)
  39. # 现在mmm就配置好,大家可以自行测试
  40. # 我的测试方法为:停掉192.168.1.101的dbserver 查看虚拟ip变化,其他几台dbserver复制的变化
  41. # 启动192.168.1.101的dbserver,停掉192.168.1.100,查看虚拟ip的变化,特别看两台slave上复制主服务器的指向

五、配置中遇到的问题

1.问题1报错如下:

ERROR: Can’t connect to monitor daemon!

可以 把debug=1 再去看日志文件,由哪些问题引起的。

2.问题2如下:

启动monitor ,ok。设置成debug模式。可以看到这样的错误:

DEBUG mysql(db2) = ‘ERROR: Connect error (host = 192.168.1.100:3306, user = mmm_monitor)! Can’t connect to MySQL server on ‘192.168.1.100’ (4)’

# 这个问题搞了半天才解决,希望大家注意:

原因:因为你的agent配置文件里写的是this db1 .this db2.在host里没有对应的解析.所以无法连接。

在/etc/hosts 添加如下语句即可[记得传送到所有机器上]:

192.168.1.100 client100.kongzhong.com

192.168.1.101 client101.kongzhong.com

192.168.1.102 client102.kongzhong.com

192.168.1.103 client103.kongzhong.com

192.168.1.104 client104.kongzhong.com

或者 在my.cnf 加入 skip-name-resolve 这个方法也是可行的!

基于开源软件cobar配置分布式数据库

这篇文章不能称之为原创,完全是基于cobar的官方文档搭建,从这里也间接的可以看到cobar的文档有多详细

一、cobar简介:
Cobar是关系型数据库的分布式处理系统,它可以在分布式的环境下看上去像传统数据库一样为您提供海量数据服务。
        产品在阿里巴巴B2B公司已经稳定运行了3年以上。
        目前已经接管了3000+个MySQL数据库的schema,为应用提供数据服务。
        据最近统计cobar集群目前平均每天处理近50亿次的SQL执行请求。
cobar官方文档地址:http://code.alibabatech.com/wiki/display/cobar/Home
二、cobar解决的问题以及cobar存在的不足:
1.cobar解决的问题:
   (1).分布式:Cobar的分布式主要是通过将表放入不同的库来实现:
       A. Cobar支持将一张表水平拆分成多份分别放入不同的库来实现表的水平拆分
       B. Cobar也支持将不同的表放入不同的库
       C. 多数情况下,用户会将以上两种方式混合使用
    这里需要强调的是,Cobar不支持将一张表,例如test表拆分成test_1, test_2, test_3…..放在同一个库中,必须将拆分后的表分别放入不同的库来实现分布式。
   (2).HA:在用户配置了MySQL心跳的情况下,Cobar可以自动向后端连接的MySQL发送心跳,判断MySQL运行状况,一旦运行出现异常,Cobar可以自动切换到备机工作。但需要强调的是:
        A. Cobar的主备切换有两种触发方式,一种是用户手动触发,一种是Cobar的心跳语句检测到异常后自动触发。那么,当心跳检测到主机异常,切换到备机, 如果主机恢复了,需要用户手动切回主机工作,Cobar不会在主机恢复时自动切换回主机,除非备机的心跳也返回异常。
        B. Cobar只检查MySQL主备异常,不关心主备之间的数据同步,因此用户需要在使用Cobar之前在MySQL主备上配置双向同步,详情可以参阅MySQL参考手册。
2.存在的不足:
   (1).不支持跨库情况下的join、分页、排序、子查询操作。
   (2).SET语句执行会被忽略,事务和字符集设置除外。
   (3).分库情况下,insert语句必须包含拆分字段列名。
   (4).分库情况下,update语句不能更新拆分字段的值。
   (5).不支持SAVEPOINT操作。
   (6).暂时只支持MySQL数据节点。
   (7).使用JDBC时,不支持rewriteBatchedStatements=true参数设置(默认为false)。
   (8).使用JDBC时,不支持useServerPrepStmts=true参数设置(默认为false)。
   (9).使用JDBC时,BLOB, BINARY, VARBINARY字段不能使用setBlob()或setBinaryStream()方法设置参数。
3.Cobar逻辑层次图
cobar

    dataSource:数据源,表示一个具体的数据库连接,与一个物理存在的schema一一对应。
   dataNode:数据节点,由主、备数据源,数据源的HA以及连接池共同组成,可以将一个dataNode理解为一个分库。
   table:表,包括拆分表(如tb1,tb2)和非拆分表。
   tableRule:路由规则,用于判断SQL语句被路由到具体哪些datanode执行。
   schema:cobar可以定义包含拆分表的schema(如schema1),也可以定义无拆分表的schema(如schema2)。
以上层次关系具有较强的灵活性,用户可以将表自由放置不同的datanode,也可将不同的datasource放置在同一MySQL实例上。
三、cobar配置实例:
1.实验场景描述及拓扑图:
   (1).系统对外提供的数据库名是dbtest,并且其中有两张表tb1和tb2。
   (2).tb1表的数据被映射到物理数据库dbtest1的tb1上。
   (3).tb2表的一部分数据被映射到物理数据库dbtest2的tb2上,另外一部分数据被映射到物理数据库dbtest3的tb2上。
如下图所示:
cobar1

2.环境准备:
(1).操作系统:linux[red hat linux 6]
(2).mysql:mysql 5.1以上版本[数据库也已经安装好,mysql 5.6.14]
(3).jdk:使用1.6以上版本[默认已经装好,如果不清楚,请看上一篇amoeba博文]
(4).cobar服务器:192.168.1.104:3306   用户名和密码:root/kongzhong
(5).数据库环境描述:
     dbtest1:192.168.1.102:3306/tb1
     dbtest2:192.168.1.102:3307/tb2
     dbtest3:192.168.1.100:3306/tb2
(6).建库脚本如下:[脚本执行就不演示了]
 
  1. #创建dbtest1脚本  
  2.    drop database if exists dbtest1;  
  3.    create database dbtest1;  
  4.    use dbtest1;  
  5.    #在dbtest1上创建tb1  
  6.    create table tb1(  
  7.    id    int not null,  
  8.    gmt   datetime);  
  9.    
  10. #创建dbtest2  
  11.    drop database if exists dbtest2;  
  12.    create database dbtest2;  
  13.    use dbtest2;  
  14.    #在dbtest2上创建tb2  
  15.    create table tb2(  
  16.    id    int not null,  
  17.    val   varchar(256));  
  18.    
  19. #创建dbtest3  
  20.    drop database if exists dbtest3;  
  21.    create database dbtest3;  
  22.    use dbtest3;  
  23.    #在dbtest3上创建tb2  
  24.    create table tb2(  
  25.    id    int not null,  
  26.    val   varchar(256));  

3.cobar配置:

cobar软件下载:http://www.kuaipan.cn/file/id_119710994921422891.htm

(1).查看jdk环境变量是否正确配置[我这里默认已经配置好,不清楚的,请看上一篇amoeba文章]

 
  1. [root@centos ~]# echo $JAVA_HOME  
  2. /usr/local/java  

(2).解压cobar压缩包,并进入解压后的目录

 
  1. [root@centos ~]# tar -xf cobar-server-1.2.7.tar.gz  
  2. [root@centos ~]# cd cobar-server-1.2.7  
  3. 在此目录下可以看到bin/conf/lib/logs四个目录,具体目录含义,查看官方文档,我们这里主要使用conf/bin两个目录  

(3).进入conf目录,配置schema.xml文件[注意:schema.xml包含MySQL的IP、端口、用户名、密码等配置,您需要按照注释替换为您的MySQL信息]

 
  1. # 这个文件主要配置cobar对外提供的数据库名和表名,以及后面真实数据库的地址和库名,登陆真实数据库的账号密码  
  2. [root@centos cobar-server-1.2.7]# cd conf/  
  3. [root@centos conf]# vim schema.xml  
  4. # 配置如下  
  5. <?xml version=”1.0″ encoding=”UTF-8″?>  
  6. <!DOCTYPE cobar:schema SYSTEM “schema.dtd”>  
  7. <cobar:schema xmlns:cobar=”http://cobar.alibaba.com/”>  
  8.    
  9.   <!– schema定义 –>  
  10.   <schema name=”dbtest” dataNode=”dnTest1″>  
  11.     <table name=”tb2″ dataNode=”dnTest2,dnTest3″ rule=”rule1″ />  
  12.   </schema>  
  13.    
  14.   <!– 数据节点定义,数据节点由数据源和其他一些参数组织而成。–>  
  15.   <dataNode name=”dnTest1″>  
  16.     <property name=”dataSource”>  
  17.       <dataSourceRef>dsTest[0]</dataSourceRef>  
  18.     </property>  
  19.   </dataNode>  
  20.   <dataNode name=”dnTest2″>  
  21.     <property name=”dataSource”>  
  22.       <dataSourceRef>dsTest[1]</dataSourceRef>  
  23.     </property>  
  24.   </dataNode>  
  25.   <dataNode name=”dnTest3″>  
  26.     <property name=”dataSource”>  
  27.       <dataSourceRef>dsTest[2]</dataSourceRef>  
  28.     </property>  
  29.   </dataNode>  
  30.    
  31.   <!– 数据源定义,数据源是一个具体的后端数据连接的表示。–>  
  32.   <dataSource name=”dsTest” type=”mysql”>  
  33.     <property name=”location”>  
  34.       <location>192.168.1.102:3306/dbtest1</location> <!–注意:替换为您的MySQL IP和Port–>  
  35.       <location>192.168.1.102:3307/dbtest2</location> <!–注意:替换为您的MySQL IP和Port–>  
  36.       <location>192.168.1.100:3306/dbtest3</location> <!–注意:替换为您的MySQL IP和Port–>  
  37.     </property>  
  38. # 这里登陆数据库的用户记得要授权  
  39.     <property name=”user“>cobar</property> <!–注意:替换为您的MySQL用户名–>  
  40.     <property name=”password”>kongzhong</property> <!–注意:替换为您的MySQL密码–>  
  41.     <property name=”sqlMode”>STRICT_TRANS_TABLES</property>  
  42.   </dataSource>  
  43. </cobar:schema>  

(4).rule.xml配置(本文仅以数字类型的id字段作为拆分字段,将数据拆分到两个库中,更详细用法可以参看官方文档)

 
  1. # 此文件主要配置拆分字段规则  
  2. [root@centos conf]# vim rule.xml  
  3. # 配置如下:  
  4. <?xml version=”1.0″ encoding=”UTF-8″?>  
  5. <!DOCTYPE cobar:rule SYSTEM “rule.dtd”>  
  6. <cobar:rule xmlns:cobar=”http://cobar.alibaba.com/”>  
  7.   <!– 路由规则定义,定义什么表,什么字段,采用什么路由算法。–>  
  8.   <tableRule name=”rule1″>  
  9.     <rule>  
  10.       <columns>id</columns>  
  11.       <algorithm><![CDATA[ func1(${id})]]></algorithm>  
  12.     </rule>  
  13.   </tableRule>  
  14.    
  15.   <!– 路由函数定义,应用在路由规则的算法定义中,路由函数可以自定义扩展。–>  
  16.   <function name=”func1″ class=”com.alibaba.cobar.route.function.PartitionByLong”>  
  17.     <property name=”partitionCount”>2</property>  
  18.     <property name=”partitionLength”>512</property>  
  19.   </function>  
  20. </cobar:rule>  

(5).server.xml配置[此文件配置对外登陆数据库的账号和密码,此账号密码不需要在数据库里授权]

 
  1. [root@centos conf]# vim  server.xml  
  2. # 配置如下:  
  3. <?xml version=”1.0″ encoding=”UTF-8″?>  
  4. <!DOCTYPE cobar:server SYSTEM “server.dtd”>  
  5. <cobar:server xmlns:cobar=”http://cobar.alibaba.com/”>  
  6.    
  7.   <!–定义Cobar用户名,密码–>  
  8.   <user name=”test”>  
  9.     <property name=”password”>test</property>  
  10.     <property name=”schemas”>dbtest</property>  
  11.   </user>  
  12. </cobar:server>  

(6).分别在三个实例里授权cobar服务器访问mysql数据库

  1. 授权语句如下:[三个实例上都需要授权]  
  2. grant all privileges on *.* to ‘coabr’@’192.168.1.104’ identified by ‘kongzhong’  

(7).启动cobar服务器

 
  1. # 进入cobar安装目录下的bin目录  
  2. [root@centos logs]# cd ../bin/  
  3. # 执行startup.sh  
  4. [root@centos bin]# ./startup.sh  
  5. “/usr/local/java/bin/java” -Dcobar.home=”/root/cobar-server-1.2.7″ -classpath “/root/cobar-server-1.2.7/conf:/root/cobar-server-1.2.7/lib/classes:/root/cobar-server-1.2.7/lib/cobar-server-1.2.7.jar:/root/cobar-server-1.2.7/lib/log4j-1.2.16.jar” -server -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+UseFastAccessorMethods -XX:+DisableExplicitGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 com.alibaba.cobar.CobarStartup >> “/root/cobar-server-1.2.7/logs/console.log” 2>&1 &  
  6. # 执行完启动命令后看日志目录下的stdout.log,显示如下信息为正常  
  7. [root@centos bin]# cd ../logs/  
  8. [root@centos logs]# more stdout.log  
  9. 22:39:50,737 INFO  ===============================================  
  10. 22:39:50,738 INFO  Cobar is ready to startup …  
  11. 22:39:50,741 INFO  Startup processors …  
  12. 22:39:50,788 INFO  Startup connector …  
  13. 22:39:50,804 INFO  Initialize dataNodes …  
  14. 22:39:50,891 INFO  dnTest1:0 init success  
  15. 22:39:50,909 INFO  dnTest3:0 init success  
  16. 22:39:50,911 INFO  dnTest2:0 init success  
  17. ………………………..  
  18. # 查看 cobar进程是否开启  
  19. [root@centos logs]# ps -ef |grep cobar  
  20. root      5843     1  0 22:17 pts/0    00:00:02 /usr/local/java/bin/java -Dcobar.home=/root/cobar-server-1.2.7 -classpath /root/cobar-server-1.2.7/conf:/root/cobar-server-1.2.7/lib/classes:/root/cobar-server-1.2.7/lib/cobar-server-1.2.7.jar:/root/cobar-server-1.2.7/lib/log4j-1.2.16.jar -server -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:+AggressiveOpts -XX:+UseBiasedLocking -XX:+UseFastAccessorMethods -XX:+DisableExplicitGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 com.alibaba.cobar.CobarStartup  
  21. root      6005  5428  0 22:41 pts/0    00:00:00 grep cobar  
  22. # 查看端口是否监听[8066为登陆端口,9066为管理端口]  
  23. [root@centos logs]# netstat -tulnap |grep 8066  
  24. tcp        0      0 :::8066                     :::*                        LISTEN      5843/java            
  25. [root@centos logs]# netstat -tulnap |grep 9066  
  26. tcp        0      0 :::9066                     :::*                        LISTEN      5843/java    

(8).登陆cobar测试,和正常登陆mysql类似

 
  1. # 指定cobar服务器ip地址,端口,账户,密码  
  2. [root@centos logs]# mysql -h192.168.1.104 -P8066 -utest -ptest  
  3. Welcome to the MySQL monitor.  Commands end with ; or \g.  
  4. Your MySQL connection id is 2  
  5. Server version: 5.1.48-cobar-1.2.7 Cobar Server (ALIBABA)  
  6. Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.  
  7. Oracle is a registered trademark of Oracle Corporation and/or its  
  8. affiliates. Other names may be trademarks of their respective  
  9. owners.  
  10. Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the current input statement.  
  11. # 这里就显示了我们对外提供的数据库  
  12. mysql> show databases;  
  13. +———-+  
  14. | DATABASE |  
  15. +———-+  
  16. | dbtest   |  
  17. +———-+  
  18. 1 row in set (0.00 sec)  
  19. mysql> use dbtest  
  20. Database changed  
  21. # 显示表  
  22. mysql> show tables;  
  23. +——————+  
  24. | Tables_in_dbtest |  
  25. +——————+  
  26. | tb1              |  
  27. | tb2              |  
  28. +——————+  
  29. 2 rows in set (0.00 sec)  
  30. # 插入数据测试  
  31. mysql> insert into tb1 (id, gmt) values (1, now());  
  32. mysql> insert into tb2 (id, val) values (1, “part1”);  
  33. mysql> insert into tb2 (id, val) values (2, “part1”), (513, “part2”);  
  34. # 查询数据  
  35. mysql> select * from tb1;    
  36. +—-+———————+  
  37. id | gmt                 |  
  38. +—-+———————+  
  39. |  1 | 2013-12-10 15:04:05 |  
  40. +—-+———————+  
  41. 1 row in set (0.01 sec)  
  42. # 仔细看下面这几个数据[这个数据时根据规则插入的,详细可以查看rules.xml]  
  43. mysql> select * from tb2;    
  44. +—–+——-+  
  45. id  | val   |  
  46. +—–+——-+  
  47. |   1 | part1 |  
  48. |   2 | part1 |  
  49. | 513 | part2 |  
  50. +—–+——-+  
  51. 3 rows in set (0.00 sec)  

(9).此时可以到后端真是的数据库服务器查看数据,此时就看到分库分表的效果
# 关闭cobar的命令在 安装目录下有个shutdown.sh 脚本
# 关于cobar的集群,在server.xml配置,个人认为这个集群就是避免cobar的单点故障,这个东西我们将在实际业务运用中再做研究

mysql 5.6 新特性中,自定义刷新日志时间:innodb_flush_log_at_timeout

      今天有一朋友发了一个参数过来(innodb_flush_log_at_timeout),着实没见过这个参数,从字面意思上理解和刷新日志有关,所以就查了一下,我这里说一下自己的观点:

      1.innodb_flush_log_at_timeout 这个参数的意思是刷新日志的时间,在mysql5.6版本中可以自定义,默认为1s。其与oracle有很大区别:
      在oracle中,有三种情况可以将日志缓冲区的数据写到在线日志文件中
      (1).日志缓冲区中的记录达到1M
      (2).每隔3秒
      (3).日志缓冲区已经用了三分之一
     2.INNODB REDO日志:InnoDB为了保证日志的刷写的高效,使用了内存的log buffer。
      由于InnoDB大部分情况下使用的是文件系统,(linux文件系统本身也是有buffer的)而不是直接使用物理块设备,这样的话就有两种丢失日志的可能性:日志保存在log_buffer中,机器挂了,对应的事务数据就丢失了;日志从log buffer刷到了linux文件系统的buffer,机器挂掉了,对应的事务数据就丢失了。
     3.InnoDB有一个参数用于设置这两个缓存的刷新: innodb_flush_log_at_trx_commit。而 innodb_flush_log_at_trx_commit  有三个值:0/1/2,默认是1。而innodb_flush_log_at_timeout 定义了每次日志刷新的时间,与  innodb_flush_log_at_trx_commit 配合使用,其具体流程,先看下图:
innodb_flush_log_at_time
innodb_flush_log_at_time
       innodb_flush_log_at_trx_commit=1,表示在每次事务提交的时候,都把log buffer刷到文件系统中(os buffer)去,并且调用文件系统的“flush”操作将缓存刷新到磁盘上去。
       innodb_flush_log_at_trx_commit=0,表示每隔一秒把log buffer刷到文件系统中(os buffer)去,并且调用文件系统的“flush”操作将缓存刷新到磁盘上去。也就是说一秒之前的日志都保存在日志缓冲区,也就是内存上,如果机器宕掉,可能丢失1秒的事务数据。
       innodb_flush_log_at_trx_commit=2,表示在每次事务提交的时候会把log buffer刷到文件系统中(os buffer)去,但是每隔一秒调用文件系统(os buffer)的“flush”操作将缓存刷新到磁盘上去。如果只是MySQL数据库挂掉了,由于文件系统没有问题,那么对应的事务数据并没有丢失。只有在数据库所在的主机操作系统损坏或者突然掉电的情况下,数据库的事务数据可能丢失1秒之类的事务数据。这样的好处,减少了事务数据丢失的概率,而对底层硬件的IO要求也没有那么高(log buffer写到文件系统中,一般只是从log buffer的内存转移的文件系统的内存缓存中,对底层IO没有压力)。MySQL 5.6.6以后,这个“1秒”的刷新还可以用innodb_flush_log_at_timeout 来控制刷新间隔。
       结合上面几个参数的描述,我相信多数企业采用mysql innodb存储引擎都是为了充分保证数据的一致性,所以,innodb_flush_log_at_trx_commit这个参数一般都是 1,这样的话,innodb_flush_log_at_timeout 的设置对其就不起作用。innodb_flush_log_at_timeout 的设置只针对 innodb_flush_log_at_trx_commit为0/2 起作用,所以,此参数可暂时不做研究!