分布式高并发下mysql数据库读写分离

读写

分离(Read/Write Splitting)。

1.原理:让主数据库(master)处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库(slave)处理SELECT查询操作。

2.诞

生原因:

2.1 为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台数据库服务器,是对外提供增删改查业务的生产服务器;第二台数据库服务器,仅仅接收来自第一台服务器的备份数据(注意,不同数据库产品,第一台数据库服务器,向第二台数据库服务器发送备份数据的方式不同)。当第一台数据库崩溃后,第二台数据库服务器,可以立即上线来代替第一台数据库服务器,并且,在第一台数据库服务器崩溃后,宝贵的数据,依然会存在于第二台数据库服务器里(根据目前业界的备份数据发送方式来看,当第一台数据库崩溃后,第一台数据库里的仍然会有少量的新数据,没能来得及被发送到第二台数据库服务器,所以,这部分数据就丢失了)。

2.2 一般来说,为了配置方便,以及稳定性,这两台数据库服务器,都用的是相同的配置(思考一下,如果两台服务器的配置不同,会导致什么结果)。

2.3 从上文的描述中,大家能看到,在实际运行中,第一台数据库服务器的压力,远远大于第二台数据库服务器。因此,很多人希望合理利用第二台数据库服务器的空闲资源。那么,第二台数据库服务器能做些什么事情呢?

2.4 从数据库的基本业务来看,数据库的操作无非就是增删改查这4个操作。但对于“增删改”这三个操作,如果是双机热备的环境中做,一台机器做了这三个操作的某一个之后,需要立即将这个操作,同步到另一台服务器上。单向的同步,不复杂。但如果两台机器都需要向对方进行同步,那逻辑就非常复杂,而且还会大大降低性能。(从保证ACID特性的角度,思考一下为什么双向同步会非常复杂且低性能?而单向同步却不会?)出于这个原因,第二台备用的服务器,就只做了查询操作。进一步,为了降低第一台服务器的压力,干脆就把查询操作全部丢给第二台数据库服务器去做,第一台数据库服务器就只做增删改了。

2.4 到这一步,就实现了所谓的读写分离。这样做,缺点也非常明显了。本来第二台数据库服务器,是用来做热备的,它就应该在一个压力非常小的环境下,保证运行的稳定性。而读写分离,却增加了它的压力,也就增加了不稳定性。因此,读写分离,实质上是一个在资金比较缺乏,但又需要保证数据安全的需求下,在双机热备方案上,做出的一种折中的扩展方案。

读写

分离

MySQL读写分离基本原理是让master数据库处理写操作,slave数据库处理读操作。master将写操作的变更同步到各个slave节点。

MySQ

L读写分离能提高系统性能的原因在于:

主从只负责各自的读和写,极大程度缓解X锁和S锁争用。

slave可以配置MyIASM引擎,提升读性能以及节约系统开销。

master直接写是并发的,slave通过主库发送来的binlog恢复数据是异步。

slave可以单独设置一些参数来提升其读的性能。

实现

方法1. MySQLProxy

MySQLProxy是在客户端请求与MySQLServer之间建立了一个连接池。所有客户端请求都是发向MySQLProxy,然后经由MySQLProxy进行相应的分析,判断出是读操作还是写操作,分发至对应的MySQLServer上。对于多节点Slave集群,也可以起做到负载均衡的效果。

1.1存

在的问题

当一个事务中先执行update,后执行select时,MySQLProxy 存在一个问题,由于它只是简单的将update打到master,select打到slave,由于mysql 主从复制是异步的,存在一定的延时,所以select 可能读取不到刚更新的数据。

2. S

harding JDBCsharding jdbc官方文档

Sharding-JDBC是当当开源的一款分库分表&读写分离框架。经过评估后,决定使用该框架。

选择原因:

测试覆盖率达到95%

代码整体框架比较清晰,方便阅读及二次开发

社区活跃度较高,且持续维护

支持JPA、Hibernate、Mybatis、Spring JDBC Template或直接使用JDBC

可基于任何第三方的数据库连接池,如DBCP、C3P0、 BoneCP、Druid等

2.1遇

到的问题

上周在开发过程中遇到一个问题。当在一个spring Transactional中,先执行select操作,后执行update操作时,报以下异常:

at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

2.2报

错原因:

首先执行select语句,sharding JDBC判断该语句打到slave数据库上,获取slave的连接并放到Transaction中

其次执行update语句,因为Transaction中已经存在slave的连接,故直接使用该连接进行update

slave配置的用户只能对数据库进行读操作,故爆出异常

2.3解

决方案

为了避免update 使用slave导致报错,故强制select & update都适用master,方法如下:

HintManager hintManager = HintManager.getInstance();hintManager.setMasterRouteOnly();

该方法会强制事务中的所有数据库操作使用master。

不要错过

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20171228G0U1B300?refer=cp_1026

同媒体快讯

相关快讯

扫码关注云+社区