admin管理员组文章数量:1584177
前段时间看了一下Mysql数据库切分方面的知识,感觉某些点还挺有技巧的,决定小小的对自己所看的知识点进行一下总结。
随着企业的不断发展,需要存储的数据不断加大,以往把数据放在单一的数据库中的做法越来越成为存取数的瓶颈,因此就对数据库提出了以下的一些要求:
1、为了降低单台数据库 负载,引入数据库切分。
2、考虑到大多数数据库操作大都“多读少写”,因此,在数据库中引入“读写分离”机制。
3、为了数据库容灾,在数据库中引入备库的思想。
基于以上需要mysql数据库可以从以下几方面入手进行改造:
一、数据库水平切分
考虑一个情况, 一个表中现在有5000w条数据,在这个表中增加(insert)一条新的数据,insert完毕后,数据库会针对这张表重新建立索引,5000w行数据建立索引的系统开销是不容忽视的。因此为了解决以上问题,我们引入了第一个数据切分的方式: 数据库内的水平切分。这种切分方式是 对数据通过一系列的切分规则,将数据分布到一个数据库的不同表中,比如将article分为article_001,article_002等子表,若干个子表水平拼合有组成了逻辑上一个完整的article表。但是这种方式仍然将读取限定在了一台数据库,因此由此产生了另外一种切分: 物理上的水平切分,即将数据分布到不同的DB服务器上,通过路由规则路由访问特定的数据库,这样一来每次访问面对的就不是单台服务器了,而是N台服务器,这样就可以降低单台机器的负载压力。
那通过哪些方法能够将数据库拆分呢,总结了下,主要有几下几点:
二、数据库的读写分离策略 由于数据库大多是“多读少写”的,同时由于写数据存在锁表的机制,因此在数据库集群内可以采用“读写分离”的机制来提高性能。具体做法是:在数据库集群内部制定一台数据库为master,另外几台为slave,并都与master通信,对数据库所有的写操作都在master端发生,而其他slave与master共同来负责读的任务,当master端写完数据后将数据传递给slave(其实是slave向master请求),这样就能做到数据的一致性。利用这种机制分散了对数据库读的负载,同时也能够控制写数据时锁表对数据库的影响。其中把数据从master端复制到slave端的操作由mysql的replication机制保证。
mysql的replication机制: replication机制的步骤如下图所示:
1、首先master在其配置中打开bin log,然后slave通过i/o线程链接到master,请求master传递bin log日志,同时请求中包括了此次需要的日志的起始标志位。 2、master收到请求后从接收到的标志位开始给slave返回内容,同时返回此次日志发送到达的记录位置,作为一下次slave请求的起始标志位。 3、slave将得到的内容记录在relay log中,同时受到的起始位置信心记录在mysql的master-info文件中。 4、另外开启一个线程,解析日志,并执行,这样master端的数据都都同步到了slave端。
其中3、4步骤是同时执行。 因此记录到relay log的信息是不断的执行,然后擦除的, 所以中继日志的开销很小,并 通常将其存入OS的缓存中,。
但是复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。
那从master端到底是复制什么内容到slave端了,一般有两种类型:
1、基于语句的复制:指日志中记录的是master端执行过的写数据库的sql语言,然后slave获取到这些sql语言后再次在自己的数据库中执行一次。这样做的好处整个复制去slave端的内容数据量小,而且清晰易懂。但由于sql中存在着now()等函数,带有这种函数的sql传递到slave端执行时now()值早已变化了,因此对着这种情况此种复制方法需要特殊处理。 2、基于记录的复制:指日志中记录的是实际数据的改变,然后复制到slave端后只需执行相应的改变即可,这样的好处是对于某些语句高效,缺点是日志不直观。
e.g 1 : mysql> INSERT INTO summary_table(col1, col2, sum_col3) values SELECT col1, col2, sum(col3) FROM enormous_table GROUP BY col1, col2; 对于这种sql语句,显然第二种复制方式对于slave数据库来说更为高效。
e.g 2 : mysql> UPDATE enormous_table SET col1 = 0; 而对着这种sql语言,第一种复制方式就只用执行一次sql语句即可,而第二种方式需要依次改变 enormous_table表的每条记录,因此第一种更为高效。
其实,仔细想想,以上的replication机制会存在问题,假设,当master端已经更新了数据A,但是还没有来得及传递到slave端,而此时两个读请求同时请求到master和slave的数据A,这样两个请求获取到得数据A将是不同的,这样就会产生“脏数据”的问题。这个问题是读写分离中遇到的最常见的问题之一,为了解决这个问题,可以采用mysql提供的proxy机制。
mysql提供的proxy机制: proxy是 一个位于client端和mysql的server端的小程序,是一个连接池,用lua脚本实现。
proxy的处理过程对于client端透明,client只需要把链接数据库的ip和端口改成proxy服务器的就行。
1、解决读写分离:client端请求时, proxy 截取出当前的请求是insert、update还是select,然后把 insert和update请求发送到Master中,把select请求发送到Slave中,这样就解决了读写分离的问题。
2、同步延迟:在master端增加只含有一个字段的自增表,当master端有数据更新时便向自增表更新记录。同时slave端也存在一个自增表,当Client通过Proxy进行数据读取时,Proxy可以先向Master和Slave的 Count_table表发送查询请求,当二者的数据相同时,Proxy可以认定 Master和Slave的数据状态是一致的,然后把select请求发送到Slave服务器上,否则就发送到Master上。如下图所示:
通过以上方式就能避免同步延迟产生的脏数据。
参考资料:
http://zhengdl126.iteye/blog/419850 http://wwwblogs/highriver/archive/2011/04/17/2019155.html http://wwwblogs/hustcat/archive/2009/12/19/1627525.html http://wwwblogs/itech/archive/2011/09/22/2185365.html
版权声明:本文标题:Mysql 切分规则及其相应机制简介 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1727933122a1138628.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论