在企业中,一般系统架构的瓶颈会出现在数据库这一部分,mysql主从架构在很大程度上解决了这部分瓶颈,但是在mysql主从同步的架构也存在很多问题;比如:1. 关于数据写入部分(也就是主库)往往很难做到扩展,虽然很多大公司在逻辑业务方面就进行对数据的拆分,比如商品库存按照区域去拆分(一个区域走一个库存也就是一个主库,然后定时同步总的库存),按照商品类型去划分(一个类型的商品走一套数据库),但是这对于很多中小型公司来说实现起来还是比较困难的; 2. 主从同步一般都是一个主库,一旦主库出现问题,就有可能直接导致整个主从同步架构崩盘,虽然发现后也是可以慢慢恢复的,但是这个恢复时间对于很多公司来说是难以接受的,今天的这篇博文就是主要给解决主库单点故障这个问题提供一个思路:
主要思路是:
1.一台主库(我们称之为master-01)提供服务,只负责数据的写入;
2.拿出一台数据库服务器(我们称之为Master-02)资源做master-01主库的从库(之间做主从同步);
3.两台主库之间做高可用,可以采用keepalived等方案(一定要保证master-01同时也要作为keepalived的主)
4.程序在调用主库IP地址的地方写为高可用的VIP地址;
5.所有提供服务的从服务器与master-02进行主从同步;
6.建议采用高可用策略的时候,当master-01出现问题切换到master-02的时候,即使master-01恢复了,也不要让它去自动承接VIP地址,否则可能造成数据的混写;
这样做可以在一定程度上保证主库的高可用,在一台主库down掉之后,可以在极短的时间内切换到另一台主库上(尽可能减少主库宕机对业务造成的影响),减少了主从同步给线上主库带来的压力;但是也有几个不足的地方:比如master-02可能会一直处于空闲状态(其实完全可以让它承担一部分从库的角色来负责一部分查询请求的),2. 这样真正提供服务的从库要等master-02先同步完了数据后才能去master-02上去同步数据,这样可能会造成一定程度的同步延迟时间的加长;3. 如果master-01一旦恢复正常,会不会导致数据写入混乱(这个可以在keepalived中设置响应的规则,让其不”夺权”,我们认为的去调整操作即可
架构的简易图如下:
具体实施方案:
1. 在所有需要提供服务的服务器上安装MySQL服务(建议源码安装)
1.1 yum安装依赖包
<ol class="dp-sql"><li class="alt"><span><span>yum -y install cmake make gcc gcc-c++ ncurses-devel bison openssl-devel </span></span></li></ol>
1.2 添加MySQL所需要的用户/组
<ol class="dp-sql"> <li class="alt"><span><span>groupadd mysql </span></span></li> <li><span>useradd -g mysql -r mysql </span></li> </ol>
1.3 下载MySQL源码包
<ol class="dp-sql"><li class="alt"><span><span>wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.36.tar.gz </span></span></li></ol>
1.4 创建MySQL安装所需要的目录
<ol class="dp-sql"><li class="alt"> <span>mkdir /data/mydata/{data</span>,<span>tmp</span>,<span>logs} –pv </span> </li></ol>
1.5 解压编译安装MySQL
<ol class="dp-sql"> <li class="alt"><span><span>tar xf mysql-5.5.36.tar.gz </span></span></li> <li><span>cd mysql-5.5.36 </span></li> <li class="alt"> <span>cmake . -DCMAKE_INSTALL_PREFIX=/usr/</span><span class="keyword">local</span><span>/mysql \ </span> </li> <li><span> -DMYSQL_DATADIR=/data/mydata/data \ </span></li> <li class="alt"><span> -DSYSCINFDIR=/etc \ </span></li> <li><span> -DWITH_INNOBASE_STORAGE_ENGINE=1 \ </span></li> <li class="alt"><span> -DWITH_ARCHIVE_STORAGE_ENGINE=1 \ </span></li> <li><span> -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ </span></li> <li class="alt"><span> -DWITH_READLINE=1 \ </span></li> <li><span> -DWITH_SSL=system \ </span></li> <li class="alt"><span> -DWITH_ZLIB=system \ </span></li> <li><span> -DWITH_LIBWARP=0 \ </span></li> <li class="alt"><span> -DWITH_UNIX_ADDR=/tmp/mysql.sock \ </span></li> <li><span> -DDEFAULT_CHARASET=uft8 \ </span></li> <li class="alt"><span> -DDEFAULT_COLLATTON=utf9_general_ci \ </span></li> <li><span>make && make install </span></li> </ol>
1.6 为MySQL提供启动脚本
<ol class="dp-sql"><li class="alt"><span><span>cp support-files/mysql.server /etc/rc.d/init.d/mysqld </span></span></li></ol>
1.7 为master-01主库提供配置文件(32G内存较为保守(满连接占用25G左右内存)的配置文件)
<ol class="dp-c"> <li class="alt"><span><span>[client] </span></span></li> <li><span>port = 3306 </span></li> <li class="alt"> <span>socket = /</span><span class="keyword">var</span><span>/lib/mysql/mysql.sock </span> </li> <li> <span class="keyword">default</span><span>-character-set = utf-8 </span> </li> <li class="alt"><span>[mysqld] </span></li> <li><span>server-id = 1 </span></li> <li class="alt"><span>port = 3306 </span></li> <li><span>user = mysql </span></li> <li class="alt"><span>basedir = /usr/local/mysql </span></li> <li><span>datadir = /data/mydata/data </span></li> <li class="alt"><span>tmpdir = /data/mydata/tmp </span></li> <li> <span>socket = /</span><span class="keyword">var</span><span>/lib/mysql/mysql.sock </span> </li> <li class="alt"><span>skip-external-locking </span></li> <li><span>skip-name-resolve </span></li> <li class="alt"> <span class="keyword">default</span><span>-storage-engine = INNODB </span> </li> <li><span>character-set-server = utf8 </span></li> <li class="alt"><span>wait-timeout = 100 </span></li> <li><span>connect_timeout = 20 </span></li> <li class="alt"><span>interactive_timeout = 100 </span></li> <li><span>back_log = 300 </span></li> <li class="alt"><span>myisam_recover </span></li> <li><span>event_scheduler = on </span></li> <li class="alt"><span>log-bin=/data/mydata/logs/mysql-bin </span></li> <li><span>binlog_format = row </span></li> <li class="alt"><span>max_binlog_size = 64M </span></li> <li><span>binlog_cache_size = 1M </span></li> <li class="alt"><span>slave-net-timeout = 10 </span></li> <li><span>skip-slave-start </span></li> <li class="alt"><span>slow_query_log = 1 </span></li> <li><span>long_query_time = 1 </span></li> <li class="alt"><span>slow_query_log_file = /data/mydata/mysqllog/logs/mysql.slow </span></li> <li><span>log-error = /data/mydata/mysqllog/logs/error.log </span></li> <li class="alt"><span>max_connections = 1000 </span></li> <li><span>max_user_connections = 1000 </span></li> <li class="alt"><span>max_connect_errors = 10000 </span></li> <li> <span>key_buffer_size = 32M #以MyISAM为主的服务器</span>,<span>要调大此值 </span> </li> <li class="alt"><span>max_allowed_packet = 64M </span></li> <li><span>table_cache = 4096 </span></li> <li class="alt"><span>table_open_cache = 4096 </span></li> <li><span>table_definition_cache = 4096 </span></li> <li class="alt"><span>sort_buffer_size = 512K </span></li> <li><span>read_buffer_size = 512K </span></li> <li class="alt"><span>read_rnd_buffer_size = 512K </span></li> <li><span>join_buffer_size = 512K </span></li> <li class="alt"><span>tmp_table_size = 64M </span></li> <li><span>max_heap_table_size = 64M </span></li> <li class="alt"><span>query_cache_type = 0 </span></li> <li><span>query_cache_size = 0 </span></li> <li class="alt"><span>bulk_insert_buffer_size = 16M </span></li> <li><span>thread_cache_size = 64 </span></li> <li class="alt"><span>thread_concurrency = 16 #CPU核数*2 </span></li> <li><span>thread_stack = 256K </span></li> <li class="alt"><span>innodb_data_home_dir = /data/mydata/data </span></li> <li><span>innodb_log_group_home_dir = /data/mydata/mysqllog/logs </span></li> <li class="alt"><span>innodb_data_file_path = ibdata1:1G:autoextend </span></li> <li><span>innodb_buffer_pool_size = 16G </span></li> <li class="alt"><span>innodb_buffer_pool_instances = 4 </span></li> <li><span>innodb_additional_mem_pool_size = 16M </span></li> <li class="alt"><span>innodb_log_file_size = 512M </span></li> <li><span>innodb_log_buffer_size = 32M </span></li> <li class="alt"><span>innodb_log_files_in_group = 3 </span></li> <li><span>innodb_flush_log_at_trx_commit = 2 </span></li> <li class="alt"><span>innodb_lock_wait_timeout = 10 </span></li> <li><span>innodb_sync_spin_loops = 40 </span></li> <li class="alt"><span>innodb_max_dirty_pages_pct = 90 </span></li> <li><span>innodb_support_xa = 1 </span></li> <li class="alt"><span>innodb_thread_concurrency = 0 </span></li> <li><span>innodb_thread_sleep_delay = 500 </span></li> <li class="alt"><span>innodb_file_io_threads = 4 </span></li> <li><span>innodb_concurrency_tickets = 1000 </span></li> <li class="alt"><span>log_bin_trust_function_creators = 1 </span></li> <li><span>innodb_flush_method = O_DIRECT </span></li> <li class="alt"><span>innodb_file_per_table #是否采用单表单空间 </span></li> <li><span>innodb_write_io_threads = 8 </span></li> <li class="alt"><span>innodb_read_io_threads = 8 </span></li> <li><span>innodb_io_capacity = 1000 </span></li> <li class="alt"> <span>innodb_file_format = Barracuda #不开启单表单空间</span>,<span>此选项无效 </span> </li> <li><span>innodb_purge_threads = 1 </span></li> <li class="alt"><span>innodb_purge_batch_size = 32 </span></li> <li><span>innodb_old_blocks_pct = 75 </span></li> <li class="alt"><span>innodb_change_buffering = all </span></li> <li><span>transaction_isolation = READ-COMMITTED </span></li> <li class="alt"><span>[mysqldump] </span></li> <li><span>quick </span></li> <li class="alt"><span>max_allowed_packet = 32M </span></li> <li><span>[mysql] </span></li> <li class="alt"><span>no-auto-rehash </span></li> <li><span>[myisamchk] </span></li> <li class="alt"><span>key_buffer_size = 64M </span></li> <li><span>sort_buffer_size = 256M </span></li> <li class="alt"><span>read_buffer = 2M </span></li> <li><span>write_buffer = 2M </span></li> <li class="alt"><span>[mysqlhotcopy] </span></li> <li><span>interactive-timeout </span></li> <li class="alt"><span>[mysqld_safe] </span></li> <li><span>open-files-limit = 10240 </span></li> </ol>
1.8 为master-02提供配置文件
<ol class="dp-sql"> <li class="alt"><span><span>master-02的配置文件仅需在master-01上稍作修改 </span></span></li> <li><span>server-id = 20 </span></li> <li class="alt"> <span>log_slave_updates = 1 #添加(将复制事件写入binlog</span>,<span>一台服务器既做主库又做从库此选项必须要开启) </span> </li> <li><span>replicate-same-server-id=0 #添加(防止MySQL循环更新) </span></li> <li class="alt"><span>relay_log_recovery = 1 #添加(MySQLrelay_log的自动修复功能) </span></li> </ol>
1.9 为从库提供配置文件(8G)
<ol class="dp-sql"> <li class="alt"><span><span>[client] </span></span></li> <li><span>port = 3306 </span></li> <li class="alt"><span>socket = /var/lib/mysql/mysql.sock </span></li> <li> <span class="keyword">default</span><span>-</span><span class="keyword">character</span><span>-</span><span class="keyword">set</span><span> = utf8 </span> </li> <li class="alt"><span>[mysqld] </span></li> <li><span>server-id = 2 </span></li> <li class="alt"><span>port = 3306 </span></li> <li> <span class="func">user</span><span> = mysql </span> </li> <li class="alt"> <span>basedir = /usr/</span><span class="keyword">local</span><span>/mysql </span> </li> <li><span>datadir = /data/mydata/data </span></li> <li class="alt"><span>tmpdir = /data/mydata/tmp </span></li> <li><span>socket = /var/lib/mysql/mysql.sock </span></li> <li class="alt"><span>skip-external-locking </span></li> <li> <span>skip-</span><span class="keyword">name</span><span>-resolve </span> </li> <li class="alt"> <span class="keyword">default</span><span>-storage-engine = INNODB </span> </li> <li> <span class="keyword">character</span><span>-</span><span class="keyword">set</span><span>-server = utf8 </span> </li> <li class="alt"><span>wait-timeout = 100 </span></li> <li><span>connect_timeout = 20 </span></li> <li class="alt"><span>interactive_timeout = 100 </span></li> <li><span>back_log = 300 </span></li> <li class="alt"><span>myisam_recover </span></li> <li> <span>event_scheduler = </span><span class="keyword">on</span><span> </span> </li> <li class="alt"><span>log-bin=/data/mydata/logs/mysql-bin </span></li> <li><span>binlog_format = row </span></li> <li class="alt"><span>max_binlog_size = 64M </span></li> <li><span>binlog_cache_size = 1M </span></li> <li class="alt"><span>slave-net-timeout = 10 </span></li> <li><span>relay_log_recovery = 1 </span></li> <li class="alt"><span>slow_query_log = 1 </span></li> <li><span>long_query_time = 1 </span></li> <li class="alt"><span>slow_query_log_file = /data/mydata/mysqllog/logs/mysql.slow </span></li> <li><span>log-error = /data/mydata/mysqllog/logs/error.log </span></li> <li class="alt"><span>max_connections = 500 </span></li> <li><span>max_user_connections = 500 </span></li> <li class="alt"><span>max_connect_errors = 10000 </span></li> <li> <span>key_buffer_size = 32M #以MyISAM为主的服务器</span>,<span>要调大此值 </span> </li> <li class="alt"><span>max_allowed_packet = 64M </span></li> <li><span>table_cache = 2048 </span></li> <li class="alt"><span>table_open_cache = 2048 </span></li> <li><span>table_definition_cache = 2048 </span></li> <li class="alt"><span>sort_buffer_size = 128K </span></li> <li><span>read_buffer_size = 128K </span></li> <li class="alt"><span>read_rnd_buffer_size = 128K </span></li> <li><span>join_buffer_size = 128K </span></li> <li class="alt"><span>tmp_table_size = 16M </span></li> <li><span>max_heap_table_size = 16M </span></li> <li class="alt"><span>query_cache_type = 0 </span></li> <li><span>query_cache_size = 0 </span></li> <li class="alt"><span>bulk_insert_buffer_size = 16M </span></li> <li><span>thread_cache_size = 64 </span></li> <li class="alt"><span>thread_concurrency = 4 #CPU核数*2 </span></li> <li><span>thread_stack = 128K </span></li> <li class="alt"><span>innodb_data_home_dir = /data/mydata/data </span></li> <li><span>innodb_log_group_home_dir = /data/mydata/mysqllog/logs </span></li> <li class="alt"><span>innodb_data_file_path = ibdata1:1G:autoextend </span></li> <li><span>innodb_buffer_pool_size = 2G </span></li> <li class="alt"><span>innodb_buffer_pool_instances = 4 </span></li> <li><span>innodb_additional_mem_pool_size = 4M </span></li> <li class="alt"><span>innodb_log_file_size = 512M </span></li> <li><span>innodb_log_buffer_size = 16M </span></li> <li class="alt"><span>innodb_log_files_in_group = 3 </span></li> <li><span>innodb_flush_log_at_trx_commit = 2 </span></li> <li class="alt"><span>innodb_lock_wait_timeout = 10 </span></li> <li><span>innodb_sync_spin_loops = 40 </span></li> <li class="alt"><span>innodb_max_dirty_pages_pct = 90 </span></li> <li><span>innodb_support_xa = 1 </span></li> <li class="alt"><span>innodb_thread_concurrency = 0 </span></li> <li><span>innodb_thread_sleep_delay = 500 </span></li> <li class="alt"><span>innodb_file_io_threads = 4 </span></li> <li><span>innodb_concurrency_tickets = 1000 </span></li> <li class="alt"><span>log_bin_trust_function_creators = 1 </span></li> <li><span>innodb_flush_method = O_DIRECT </span></li> <li class="alt"><span>innodb_file_per_table #是否采用单表单空间 </span></li> <li><span>innodb_write_io_threads = 8 </span></li> <li class="alt"><span>innodb_read_io_threads = 8 </span></li> <li><span>innodb_io_capacity = 1000 </span></li> <li class="alt"> <span>innodb_file_format = Barracuda #不开启单表单空间</span>,<span>此选项无效 </span> </li> <li><span>innodb_purge_threads = 1 </span></li> <li class="alt"><span>innodb_purge_batch_size = 32 </span></li> <li><span>innodb_old_blocks_pct = 75 </span></li> <li class="alt"> <span>innodb_change_buffering = </span><span class="op">all</span><span> </span> </li> <li> <span>transaction_isolation = </span><span class="keyword">READ</span><span>-</span><span class="keyword">COMMITTED</span><span> </span> </li> <li class="alt"><span>[mysqldump] </span></li> <li><span>quick </span></li> <li class="alt"><span>max_allowed_packet = 32M </span></li> <li><span>[mysql] </span></li> <li class="alt"> <span class="keyword">no</span><span>-auto-rehash </span> </li> <li><span>[myisamchk] </span></li> <li class="alt"><span>key_buffer_size = 64M </span></li> <li><span>sort_buffer_size = 256M </span></li> <li class="alt"><span>read_buffer = 2M </span></li> <li><span>write_buffer = 2M </span></li> <li class="alt"><span>[mysqlhotcopy] </span></li> <li><span>interactive-timeout </span></li> <li class="alt"><span>[mysqld_safe] </span></li> <li> <span class="keyword">open</span><span>-files-limit = 10240 </span> </li> </ol>
1.10 初始化MySQL
<ol class="dp-xml"><li class="alt"><span><span>/usr/local/mysql/scripts/mysql_install_db </span><span class="attribute">--user</span><span>=</span><span class="attribute-value">mysql</span><span> </span><span class="attribute">--datadir</span><span>=/data/mydata/data/ </span><span class="attribute">--basedir</span><span>=/usr/local/mysql </span></span></li></ol>
1.11 为启动脚本赋予可执行权限并启动MySQL
<ol class="dp-xml"> <li class="alt"><span><span>chmod +x /etc/rc.d/init.d/mysqld </span></span></li> <li><span>/etc/init.d/mysqld start </span></li> </ol>
2. 配置master-01
2.1 添加主从同步账户
<ol class="dp-xml"> <li class="alt">mysql> grant replication slave on *.* to 'repl'@'192.168.237.%' idetified by '123456'; </li> <li> <span>mysql</span><span class="tag">></span><span> flush privileges</span>;<span> </span> </li> </ol>
2.2 查看主库的状态
<ol class="dp-xml"> <li class="alt">mysql> show master status; </li> <li><span>+------------------+----------+--------------+------------------+ </span></li> <li class="alt"><span>| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | </span></li> <li><span>+------------------+----------+--------------+------------------+ </span></li> <li class="alt"><span>| mysql-bin.000009 | 652 | | | </span></li> <li><span>+------------------+----------+--------------+------------------+ </span></li> <li class="alt"><span>1 row in set (0.01 sec) </span></li> </ol>
2.3 因为这是测试环境,可以保证没数据写入,否则需要先锁表-->查看状态-->备份数据-->查看状态(保证没变)-->解锁表
3. 配置master-02
3.1 配置master-02为master-01的从
<ol class="dp-xml"> <li class="alt"><span><span>#若是线上有数据需要先导入数据 </span></span></li> <li> <span>mysql</span><span class="tag">></span><span> CHANGE MASTER TO </span> </li> <li class="alt"> <span> -</span><span class="tag">></span><span> </span><span class="attribute">MASTER_HOST</span><span>=</span><span class="attribute-value">'192.168.237.128'</span>,<span> </span> </li> <li> <span> -</span><span class="tag">></span><span> </span><span class="attribute">MASTER_PORT</span><span>=</span><span class="attribute-value">3306</span>,<span> </span> </li> <li class="alt"> <span> -</span><span class="tag">></span><span> </span><span class="attribute">MASTER_USER</span><span>=</span><span class="attribute-value">'repl'</span>,<span> </span> </li> <li> <span> -</span><span class="tag">></span><span> </span><span class="attribute">MASTER_PASSWORD</span><span>=</span><span class="attribute-value">'123456'</span>,<span> </span> </li> <li class="alt"> <span> -</span><span class="tag">></span><span> </span><span class="attribute">MASTER_LOG_FILE</span><span>=</span><span class="attribute-value">'mysql-bin.000009'</span>,<span> </span> </li> <li> <span> -</span><span class="tag">></span><span> </span><span class="attribute">MASTER_LOG_POS</span><span>=</span><span class="attribute-value">652</span>;<span> </span> </li> <li class="alt"> <span>Query OK</span>,<span> 0 rows affected (0.03 sec) </span> </li> <li> <span>mysql</span><span class="tag">></span><span> start slave</span>;<span> </span> </li> <li class="alt"> <span>mysql</span><span class="tag">></span><span> show slave status \G </span> </li> <li><span> Slave_IO_Running: Yes #确保为yes </span></li> <li class="alt"><span> Slave_SQL_Running: Yes #确保为yes </span></li> </ol>
3.2 配置master-02的同步用户
<ol class="dp-xml"> <li class="alt">mysql> grant replication slave on *.* to 'repl’@’192.168.237.%' identified by '123456'; </li> <li> <span>mysql</span><span class="tag">></span><span> flush privileges</span>;<span> </span> </li> </ol>
3.3 查看master-02的状态
<ol class="dp-xml"> <li class="alt">mysql> show master status; </li> <li><span>+------------------+----------+--------------+------------------+ </span></li> <li class="alt"><span>| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | </span></li> <li><span>+------------------+----------+--------------+------------------+ </span></li> <li class="alt"><span>| mysql-bin.000004 | 689 | | | </span></li> <li><span>+------------------+----------+--------------+------------------+ </span></li> <li class="alt"><span>1 row in set (0.00 sec) </span></li> </ol>
4. 从库根据上面步骤配置为master-02的从即可(为了节省篇幅不再一一赘述)
5. 在master-01上创建一个数据库测试同步效果
6. 去master-02跟从库上分别查看是否已经同步过数据来
好了,至此数据同步已经完成,关于keepalived实现双主高可用,我会在下篇keepalived实现MySQL高可用总给大家写出!!!