实战互联网公司数据存储解决方案
Posted tanhualang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实战互联网公司数据存储解决方案相关的知识,希望对你有一定的参考价值。
a. 网站架构图:2
b. 普通数据之间的同步方案:2
d. 数据库的同步方案:2
e. 互联网公司从初期到后期的数据库架构拓展3
f. 数据库主从复制解决的问题3
① 负载均衡 3
② 数据备份 3
③ 数据分布 3
④ 升级测试 3
g. 主从复制原理 画图 ,每个人必须会,面试必备:3
h. 主从同步的应用场景及切换从库不丢数据多方案介绍5
主从复制条件9
① .3个线程,主库IO,从库IO和SQL及作用9
② master.info(从库)作用9
③ .relay-log 作用9
④ 异步复制9
⑤ .binlog作用(如果需要级联需要开启Binlog)9
设置server-id,此处ID不可以相同否则最后出现IO错误9
1 row in set (0.00 sec)11
2.5、添加新slave服务器 17
问题一:18
问题二:18
问题三:18
问题四:18
问题五:19
问题六:19
1)选择一个不对外提供服务的从库,这样可以确保和主库更新最接近,专门做数据备份用21
2)开启从库的binlog功能。21
a.网站架构图:
想一想如果上面网站数据库挂掉了,能多久恢复!你们公司数据是怎么保障不丢失一致性的!
b.普通数据之间的同步方案:
① nfs网络文件共享
② samba共享数据
③ 定时任务结合rsync ,scp
④ inotify+rsync触发式实时数据同步
⑤ ftp数据同步
⑥ ssh key+scp/rsync
⑦ svn git版本管理
⑧ 文件级别也可以利用mysql,mongodb等软件作为容器实现。
⑨ 程序向两个服务器同时写入数据,双写就是一个同步机制 特点:简单、方便、效率和文件系统级别要差一点,但是同步的节点可以提供访问。 软件的自身同步机制(mysql,oracle,mongdb,ttserver,redis….)文件放到数据库,同步到从库,再把文件拿出来。
⑩ DRBD文件系统级别(基于块设备复制,直接复制block)
c.
d.数据库的同步方案:
1.自身同步机制: mysql replication,mysql主从复制(逻辑的SQL重写)物理复制方法<===drbd(从库不提供读写) oracle dataguard(物理的磁盘块,逻辑的SQL语句重写)9i从库不提供腹泻的,11g的从库实现了readonly
2.第三方drbd
e.互联网公司从初期到后期的数据库架构拓展
f.数据库主从复制解决的问题
① 负载均衡
② 数据备份
③ 数据分布
④ 升级测试
g. 主从复制原理 画图 ,每个人必须会,面试必备:
mysql的主从复制是一个异步的复制过程(虽然一般情况下感觉是实时的),数据将从一个mysql数据库(我们称之为master)复制到另一个mysql数据库(我们称之为slave),在master与slave之间实现整个主从复制的过程是由三个线程参与完成的,其中有两个线程(SQL线程和IO线程)在slave端,另外一个线程(I/O线程)在master端,要实现mysql的主从复制,首先必须打开master端的binlog记录功能,否则就无法实现,因为整个复制过程实际上就是slave从master端获取binlog日志,然后在slave上以相同顺序执行获取的binlog日志中所记录的各种SQL操作.
背下来:
(1)master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
(2) slave将master的binary log events拷贝到它的中继日志(relay log);
(3) slave重做中继日志中的事件,将更改应用到自己的数据上。
详细过程:
1)在Slave 服务器上执行sart slave命令开启主从复制开关,开始进行主从复制。
2)此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接master服务器,并请求从执行binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change
master命令指定的)之后开始发送binlog日志内容
3)Master服务器接收到来自Slave服务器的IO线程的请求后,其上负责复制的IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在Master服务器端记录的IO线程。返回的信息中除了binlog中的下一个指定更新位置。
4)当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(Mysql-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容
5)Slave服务器端的SQL线程会实时检测本地Relay Log 中IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点
h.主从同步的应用场景及切换从库不丢数据多方案介绍
单向的主从复制图,此架构只能在master端进行数据写入(生产环境可以使用)
双向的主主同步逻辑图,此架构可以在master1端或master2端进行数据写入(生产环境不建议使用)
线性级联单向双主同步逻辑图,此架构只能在master1端进行数据写入(生产环境可以使用)
环状级联单向多主同步逻辑图,任意一个都可以写入数据(生产环境不建议使用)
环状级联单向多主多从同步逻辑图,此架构只能在任意一个master端进行数据写入(生产环境不建议使用)
i.常见互联网生产实战大并发数据库解决方案,根据企业业务拆分业务应用到不同的从库思想
越是想玩牛b的架构,维护起来越难。维护成本越高, 所以95%的公司都是一主,宕机后手工提升一台从电脑为主,因为80%都是读多写少,主库做好监控,即使宕机也不会影响到什么
j.主从复制的小结:
- 主从复制是异步的逻辑的SQL语句级的复制
- 复制时,主库有一个I/O线程,从库有两个线程,I/O和SQL线程
- 实现主从复制的必要条件是主库要开启记录binlog功能
- 作为复制的所有Mysql节点的server-id都不能相同
- binlog文件只记录对数据库有更改的SQL语句(来自主库内容的变更),不记录任何查询(select,show)语句
k.主从复制实战演示:
主从复制条件
1、开启Binlog功能
2、主库要建立账号
3、从库要配置master.info(CHANGE MASTER to...相当于配置密码文件和Master的相关信息)
4、start slave 开启复制功能
主要必须记住掌握理解的知识点:
① .3个线程,主库IO,从库IO和SQL及作用
② master.info(从库)作用
③ .relay-log 作用
④ 异步复制
⑤ .binlog作用(如果需要级联需要开启Binlog)
l.实战案例一:企业刚安装好的数据库进行单向的主从复制图,此架构只能在master端进行数据写入(小企业里生产环境最常用的情况)
实验拓扑:
在备库上做备份,这样减轻数据库服务压力
主库配置:vim /etc/my.cnf
Log-bin=mysql-bin //打开二进制日志
Server-id=40 //配置servere id 通常建议大家使用ip地址最后一位来作为id号,这样便于维护和管理
设置server-id,此处ID不可以相同否则最后出现IO错误
/etc/init.d/mysqld start //重启mysql进程
Mysql> reset master; //清空掉所有二进制日志,让数据库回到初始化状态
Mysql>grant replication slave,replication client on *.* to [email protected]’172.16.10.%’ identified by ‘123’;
Mysql> flush privileges;
show master status;
备库配置:vim /etc/my.cnf
Server-id=60
Mysql>change master to master_host=’172.16.10.40’, #这是主库的IP(域名也可以需要做解析) master_user=’rep1’, #这是主库上创建用来复制的用户rep1 master_password=’123’, #rep的密码
master_log_file=’mysql-bin.000001’,#这里是show master status时看到的查询二进制日志文件名称,这里不能多空格
master_log_pos=0; #这里是show master status时看到的二进制日志偏移量,不能多空格
Mysql>Start slave;
查看主从复制状态
Mysql>show slave statusG
mysql> show slave statusG
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.10.40
Master_User: rep1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 349
Relay_Log_File: localhost-relay-bin.000002
Relay_Log_Pos: 495
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 349
Relay_Log_Space: 655
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 40
1 row in set (0.00 sec)
mysql>
在这里主要是看:
Slave_IO_Running:Yes,这是I/O线程状态,I/O线程负载从从库去主库读取binlog日志,并写入从库的中继日志中,状态为Yes表示I/O线程工作正常。
Slave_SQL_Running:Yes 这个是SQL线程状态,SQL线程负载读取中继日志(relay-log)中的数据并转换为SQL语句应用到从库数据库中,状态为Yes表示I/O线程工作正常
Seconds_Behind_Master:0 这个是在复制过程中,从库比主库延迟的描述,这个参数很重要,但企业里更准确地判断主从延迟的方法为:在主库写时间戳,然后从库读取时间戳进行比较,从而认定是否延迟。
slave的I/O和SQL线程都已经开始运行,而且Seconds_Behind_Master不再是NULL。日志的位置增加了,意味着一些事件被获取并执行了。如果你在master上进行修改,你可以在slave上看到各种日志文件的位置的变化,同样,你也可以看到数据库中数据的变化。
你可查看master和slave上线程的状态。在master上,你可以看到slave的I/O线程创建的
查看连接的线程,每一个线程代表一个从库连接: show processlistG
行2为处理slave的I/O线程的连接。
测试结果:
在主库上创建数据库表插入数据,然后看看从库是否同步:
查看数据库show databases;
创建数据库create database Myschool;
实例创建学生信息表
Create table stu(
Stunum varchar(6),
Stuname varchar(20),
Stuage tinyint(2),
);
insert into stu values(‘001‘,‘luliechu‘,‘18‘);
m.从库提升主库步骤
mysql主从复制中,需要将备库(从库)提升为主库,需要取消其从库角色,可以通过执行以下命令:
① stop slave;
② reset slave all;
③ RESET SLAVE ALL是清除从库的同步复制信息,包括连接信息和二进制文件名、位置
④ 从库上执行这个命令后,使用show slave status将不会有输出
n.实战案例二: 运行一段时间后有数据的数据库之间进行复制,采用级联方式(并发量业务量大的互联网公司解决方案)
实验拓扑
因为主库和分发主库已经运行了一段时间,有大量的数据存在,所以在这种情况下,对于新加入的从库172.16.10.70,必须要做的是先把主库数据同步到新从库哪里,然后再到分发库里同步二进制日志到从库
主库配置:vim /etc/my.cnf
Log-bin=mysql-bin //打开二进制日志
Server-id=40
Service mysqld start //重启mysql进程
Mysql> reset master;
Mysql>grant replication slave,replication client on *.* to [email protected]’172.16.10.%’ identified by ‘123’;
Mysql> flush privileges;
分发库配置:vim /etc/my.cnf
Log-bin=mysql-bin //打开二进制日志
Server-id=60
Relay_log=mysql_relay-bin
Log_slave_updates=1
Read_only=1 ead-only参数选项可以让从服务器只允许来自服务器线程或具有SUPER权限的数据库用户进行更新,可以确保从服务器不接受来自用户端的非法用户更新。
read-only参数具有允许数据库更新的条件为:
具有SUPER权限的用户可以更新,不受read-only参数影响,例如:管理员root。
来自从服务器线程可以更新,不受read-only参数影响,例如:rep用户
在生产环境中,可以在从库Slave中使用read-only参数,确保从库数据不被非法更新。
Service mysqld start //重启mysql进程
Mysql> reset master; //清空掉所有二进制日志,让数据库回到数据化状态
Mysql>change master to master_host=’172.16.10.40’, master_user=’rep1’, master_password=’tianyun’, master_log_file=’mysql-bin.000001’, master_log_pos=0;
Mysql>Start slave;
注意事项:我这种配置是给他作为一个分发主库来做的,但是它开启二进制日志其实也没有用的,这个日志并不是它自身的
初始化备库(使其和当前主库数据一致)
在这种操作情况下需要同时开两个窗口,先锁表,然后另一个窗口进行备份和查看二进制日志,等这两部看到操作完成后,再把表解锁
分发Master上配置:
Mysql>flush tables with read lock; 一边窗口
另外一边窗口# mysqldump -uroot -p"123" --lock-all-tables --all-databases>all.sql #mysql -e ‘show master status’
# mysql -u root -p123 -e ‘show master status‘
操作完之后可以回到另一边窗口过来解锁,使其可以工作了
Mysql>unlock tables;
将完备下来的数据库文件拷到从库2上
#rsync -av all.sql 172.16.10.70:/
在从库2上操作
Slave2:
Mysql>source /all.sql
mysql> quit;
# /etc/init.d/mysqld stop
Shutting down MySQL. SUCCESS!
vim /etc/my.cnf
从库2的配置:
vim /etc/my.cnf
Server-id=70
Read_only=1
Service mysqld start //重启mysql进程
Mysql> reset master;
mysql> change master to master_host=‘172.16.10.60‘, master_user=‘rep1‘, master_password=‘123‘, master_log_file=‘mysql-bin.000001‘, master_log_pos=1432;
注意事项:master_log_file=‘mysql-bin.000001‘, master_log_pos=1432;
这两个东西绝对不是乱填的,而是刚才分发库上查到的,非常重要,否则会出大问题!
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave statusG
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.16.10.60
Master_User: rep1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 1432
Relay_Log_File: localhost-relay-bin.000002
Relay_Log_Pos: 253
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
可以看到已经成功万无一失了。
测试,在主库上做数据库的增删改,看看另外两台数据库数据是否同步一致:
不想敲sql语句的可以利用数据库图形化工具操作,我这里为了方便快速测试,用它在主库40上创建了数据库和表以及插入了数据
查看其它两台是否同步:
----------------------------------------------很明显数据完全一致,整个实验成功完成--------------------------
小结:
为了开始复制,你可以运行:
mysql> START SLAVE;
运行SHOW SLAVE STATUS查看输出结果:
在slave服务器上运行该语句:
mysql> show processlist G
2.5、添加新slave服务器
假如master已经运行很久了,想对新安装的slave进行数据同步,甚至它没有master的数据。
此时,有几种方法可以使slave从另一个服务开始,例如,从master拷贝数据,从另一个slave克隆,从最近的备份开始一个slave。Slave与master同步时,需要三样东西:
(1)master的某个时刻的数据快照;
(2)master当前的日志文件、以及生成快照时的字节偏移。这两个值可以叫做日志文件坐标(log file coordinate),因为它们确定了一个二进制日志的位置,你可以用SHOW MASTER STATUS命令找到日志文件的坐标;
(3)master的二进制日志文件。
可以通过以下几中方法来克隆一个slave:
(1) 冷拷贝(cold copy)
停止master,将master的文件拷贝到slave;然后重启master。缺点很明显。
(2) 热拷贝(warm copy)
如果你仅使用MyISAM表,你可以使用mysqlhotcopy拷贝,即使服务器正在运行。
(3) 使用mysqldump
使用mysqldump来得到一个数据快照可分为以下几步:
<1>锁表:如果你还没有锁表,你应该对表加锁,防止其它连接修改数据库,否则,你得到的数据可以是不一致的。如下:
mysql> FLUSH TABLES WITH READ LOCK;
<2>在另一个连接用mysqldump创建一个你想进行复制的数据库的转储:
shell> mysqldump --all-databases --lock-all-tables >dbdump.db
<3>对表释放锁。
mysql> UNLOCK TABLES;
- o.Mysql主从复制延迟问题原因及解决方法
问题一:
一个主库的从库太多,导致复制延迟。
建议从库数量3-5 为宜,要复制的从节点数量过多,会导致复制延迟
问题二:
从库硬件比主库差,导致复制延迟
查看master和slave的系统配置,可能会因为机器配置的问题,包括磁盘IO、CPU、内存等各方面因素造成复制的延迟,一般发生在高并发大数据量写入场景。
问题三:
慢SQL语句过多
假如一条SQL语句,执行时间是20秒,那么从库执行完毕,到从库上能查到数据也至少是20秒,这样就延迟20秒了
SQL语句的优化一般要作为常规工作不断的监控和优化,如果是单个SQL的写入时间长,可以修改后分多次写入,通过查看慢查询日志或show full processlist 命令找出执行时间长的查询语句或者打的事务。
问题四:
主从复制的设计问题
例如,主从复制单线程,因为主库写并发太大,来不及传送到从库就会导致延迟。
更高版本的MySQL可以支持多线程复制,门户网站会开发自己多线程同步功能。
问题五:
主从库之间的网络延迟。
主库的网卡、网线、连接的交换机等网络设备都可能成为复制的瓶颈,导致复制延迟,另外,跨公网主从复制很容易导致主库复制延迟
问题六:
主库读写压力大,导致复制延迟
主库硬件要搞好一点,架构的前端要加buffer以及缓存层。
通过read-only参数让从库只读访问
read-only参数选项可以让从服务器只允许来自服务器线程或具有SUPER权限的数据库用户进行更新,可以确保从服务器不接受来自用户端的非法用户更新。
read-only参数具有允许数据库更新的条件为:
具有SUPER权限的用户可以更新,不受read-only参数影响,例如:管理员root。
来自从服务器线程可以更新,不受read-only参数影响,例如:rep用户
在生产环境中,可以在从库Slave中使用read-only参数,确保从库数据不被非法更新。
p.查看二进制日志:
[[email protected] ~]# mysqlbinlog mysql-bin.000001
q.Web用户专业设置方案:MySQL主从复制读写分离集群
专业的运维人员提供给开发人员的读写分离的账户设置如下:
1)访问主库和从库时使用一套用户密码,例如,用户名:web,密码:123456
2)即使访问IP不同,端口也尽量相同(3306)。例如:写库VIP为10.0.0.1 ,读库VIP为10.0.0.2
除了IP没办法修改之外,要尽量为开发人员提供方便,如果数据库前端有DAL层(DBPROXY代理)还可以只给开发人员一套用户、密码、IP、端口,这样就更专业了,剩下的都是由运维搞定。
如何给开发授权权限
方法1:主库和从库使用不同的用户,授权不同的权限。
主库上对web_w用户授权如下:
用户:web_w 密码:123456 端口3306 主库VIP:10.0.0.1
权限:SELECT,INSERT,UPDATE,DELETE
命令:GRANT SELECT,INSERT,UPDATE,DELETE ON wen.* to ‘web_w‘@10.0.0.% identified by ‘123456‘;
从库对web_r用户授权如下:
用户:web_r 密码:123456 端口:3306 从库VIP:10.0.0.2
权限:SELECT
命令:GRANT SELECT ON web.* TO [email protected]% identfied by ‘123456‘;
提示:此方法显得不够专业,但是可以满发开发需求。
方法2:主库和从库使用相同的用户,但授予不同的权限。(由于主从同步 有一些可能无法同步)
主库上对web用户授权如下:
用户:web 密码:123456 端口:3306 主库VIP:10.0.0.1
权限:SELECT,INSERT,UPDATE,DELETE
命令:GRANT SELECT,INSERT,UPDATE,DELETE ON web.* TO [email protected]% identified by ‘123456‘;
从库上对web用户授权如下:
用户:web 密码:123456 端口:3306 从库VIP:10.0.0.2
权限:SELECT
#由于主库和从库是同步复制的,所以从库上的Web用户会自动和主库一直,既无法实现只读select的权限
方法3:在从库上设置read-only参数,让从库只读
主库和从库:主库和从库使用相同的用户,授予相同的权限(非ALL权限)推荐做法,我在公司就是这么干的
用户:web 密码:123546 端口:3306 主库VIP:10.0.0.8
权限:SELECT,INSERT,UPDATE,DELETE
命令:GRANT SELECT,INSERT,UPDATE,DELETE ON web.* to [email protected]% identified by ‘123546‘;
由于从库设置了read-only,非super权限是无法写入的,因为通过read-only参数就可以
忽略授权库Mysql同步,主库配置参数如下:
binlog-ignore-db = mysql
replicate-ignore-db = mysql
r.MySQL主从复制集群架构的数据备份策略
有了主从复制,还需要做定时全量备份 因为,如果主库有语句误操作(例如:drop database oldboy;)从库也会执行drop,这样MySQL从库就都删除了该数据。
把从库作为数据备份服务器时,备份策略如下:
高并发业务场景备份时,可以选择在一台从库上备份(Slave)把从库作为数据备份服务器时需要在从库binlog功能。
1)选择一个不对外提供服务的从库,这样可以确保和主库更新最接近,专门做数据备份用
2)开启从库的binlog功能。
备份时可以选择只停止SQL线程,停止应用SQL语句到数据库,I/O线程保留工作状态,执行命令为stop slave sql_thread;备份方式可以采取mysqldump逻辑备份或者直接物理备份,例如使用cp、tar(针对目录)工具,或xtrabackup(第三方的物理备份软件)进行备份,逻辑备份和物理备份的选择,一般是根据总的备份数据量的多少进行选择,数据库低于20G,建议选择mysqldump逻辑备份方法,安全稳定,最后把全量和binlog数据发送到备份服务器上留存。
Mysql读写分离实现水平扩展:做这个之间必须要做好主从复制才行
s.解决大并发解决方案Mysql读写分离技术
方法一:基于程序代码内部实现:这类方法是目前生产环境中应用最广泛的,我们公司是程序员来实现的
在代码中根据insert,select进行选择分类,这类方法是目前生产环境中应用最广泛的
优点:性能好,因为在程序代码中实现,不需要增加额外的设备作为硬件支持,缺点是需要开发人员来实现,运维人员无从下手
方法二:基于中间代理层实现 运维人员主要学习这个
代理一般是位于客户端和服务器之间,代理服务器接到客户端请求后通过判断然后转发到后端数据库,目前主要有两个代表性程序
Mysql_proxy:mysql开源项目,通过其自带的lua脚本进行sql判断
Amoeba:由陈思儒开发,作者就职于阿里巴巴,该程序由java进行开发 这个使用比较多
t.生产管理核心思想:
以上是关于实战互联网公司数据存储解决方案的主要内容,如果未能解决你的问题,请参考以下文章
FIL官方高度评价的真实数据存储方案,西部世界看到未来引爆IPFS应用