数据库读写分离

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介:

随着一 个网站的业务不断扩展,数据不断增加,数据库的压力也会越来越大,对数据库或者SQL的基本优化可能达不到最终的效果,我们可以采用读写分离的策略来改变 现状。读写分离现在被大量应用于很多大型网站,这个技术也不足为奇了。ebay就做得非常好。ebay用的是oracle,听说是用Quest Share Plex 来实现主从复制数据。

     读写分离简单的说是把对数据库读和写的操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力。主数据库提供写操作,从数据库提 供读操作,其实在很多系统中,主要是读的操作。当主数据库进行写操作时,数据要同步到从的数据库,这样才能有效保证数据库完整性。 Quest SharePlex 就是比较牛的同步数据工具,听说比oracle本身的流复制还好,MySQL也有自己的同步数据技术。mysql只要是通过二进制日志来复制数据。通过日志在从数据库重复主数据库的操作达到复制数据目的。这个复制比较好的就是通过异步方法,把数据同步到从数据库。

      主数据库同步到从数据库后,从数据库一般由多台数据库组成这样才能达到减轻压力的目的。读的操作怎么样分配到从数据库上?应该根据服务器的压力把读的操作分配到服务器,而不是简单的随机分配。mysql提供了 MySQL-Proxy实现读写分离操作。不过MySQL-Proxy好像很久不更新了。oracle可以通过F5有效分配读从数据库的压力。


ebay的读写分离(网上找到就拿来用了)



 mysql的读写分离
       上面说的数据库同步复制,都是在从同一种数据库中,如果我要把oracle的数据同步到mysql中,其实要实现这种方案的理由很简单,mysql免费,oracle太贵。好像 Quest SharePlex 也实现不了改功能吧。好像现在市面还没有这个工具吧。那样应该怎么实现数据同步?其实我们可以考虑自己开发一套同步数据组件,通过消息,实现异步复制数据。其实这个实现起来要考虑很多方面问题,高并发的问题,失败记录等。其实这种方法也可以同步数据到 memcache 中。 听说oracle的Stream也能实现,不过没有试过。

Java代码   收藏代码
  1. public function isReadOperation($sql) {  
  2.     return preg_match('/^\s*(SELECT|SHOW|DESC|PRAGMA)\s+/i',$sql);  
  3. }  

php读写分离类

Php代码   收藏代码
  1. <?php  
  2. /**************************************** 
  3. *** mysql-rw-php version 0.1 @ 2009-4-16 
  4. *** code by hqlulu#gmail.com 
  5. *** http://www.aslibra.com 
  6. *** http://code.google.com/p/mysql-rw-php/ 
  7. *** code modify from class_mysql.php (uchome) 
  8. ****************************************/  
  9.   
  10. class mysql_rw_php {  
  11.   
  12.     //查询个数  
  13.     var $querynum = 0;  
  14.     //当前操作的数据库连接  
  15.     var $link = null;  
  16.     //字符集  
  17.     var $charset;  
  18.     //当前数据库  
  19.     var $cur_db = '';  
  20.   
  21.     //是否存在有效的只读数据库连接  
  22.     var $ro_exist = false;  
  23.     //只读数据库连接  
  24.     var $link_ro = null;  
  25.     //读写数据库连接  
  26.     var $link_rw = null;  
  27.   
  28.     function mysql_rw_php(){  
  29.     }  
  30.   
  31.     function connect($dbhost$dbuser$dbpw$dbname = ''$pconnect = 0, $halt = TRUE) {  
  32.         if($pconnect) {  
  33.             if(!$this->link = @mysql_pconnect($dbhost$dbuser$dbpw)) {  
  34.                 $halt && $this->halt('Can not connect to MySQL server');  
  35.             }  
  36.         } else {  
  37.             if(!$this->link = @mysql_connect($dbhost$dbuser$dbpw)) {  
  38.                 $halt && $this->halt('Can not connect to MySQL server');  
  39.             }  
  40.         }  
  41.           
  42.         //只读连接失败  
  43.         if(!$this->link && !$haltreturn false;  
  44.           
  45.         //未初始化rw时,第一个连接作为rw  
  46.         if($this->link_rw == null)  
  47.             $this->link_rw = $this->link;  
  48.   
  49.         if($this->version() > '4.1') {  
  50.             if($this->charset) {  
  51.                 @mysql_query("SET character_set_connection=$this->charset, character_set_results=$this->charset, character_set_client=binary"$this->link);  
  52.             }  
  53.             if($this->version() > '5.0.1') {  
  54.                 @mysql_query("SET sql_mode=''"$this->link);  
  55.             }  
  56.         }  
  57.         if($dbname) {  
  58.             $this->select_db($dbname);  
  59.         }  
  60.     }  
  61.   
  62.     //连接一个只读的mysql数据库  
  63.     function connect_ro($dbhost$dbuser$dbpw$dbname = ''$pconnect = 0){  
  64.         if($this->link_rw == null)  
  65.             $this->link_rw = $this->link;  
  66.         $this->link = null;  
  67.         //不产生halt错误  
  68.         $this->connect($dbhost$dbuser$dbpw$dbname$pconnect, false);  
  69.         if($this->link){  
  70.             //连接成功  
  71.             //echo "link ro sussess!<br>";  
  72.             $this->ro_exist = true;  
  73.             $this->link_ro = $this->link;  
  74.             if($this->cur_db){  
  75.                 //如果已经选择过数据库则需要操作一次  
  76.                 @mysql_select_db($this->cur_db, $this->link_ro);  
  77.             }  
  78.         }else{  
  79.             //连接失败  
  80.             //echo "link ro failed!<br>";  
  81.             $this->link = &$this->link_rw;  
  82.         }  
  83.     }  
  84.   
  85.     //设置一系列只读数据库并且连接其中一个  
  86.     function set_ro_list($ro_list){  
  87.         if(is_array($ro_list)){  
  88.             //随机选择其中一个  
  89.             $link_ro = $ro_list[array_rand($ro_list)];  
  90.             $this->connect_ro($link_ro['dbhost'], $link_ro['dbuser'], $link_ro['dbpw']);  
  91.         }  
  92.     }  
  93.   
  94.     function select_db($dbname) {  
  95.         //同时操作两个数据库连接  
  96.         $this->cur_db = $dbname;  
  97.         if($this->ro_exist){  
  98.             @mysql_select_db($dbname$this->link_ro);  
  99.         }  
  100.         return @mysql_select_db($dbname$this->link_rw);  
  101.     }  
  102.   
  103.     function fetch_array($query$result_type = MYSQL_ASSOC) {  
  104.         return mysql_fetch_array($query$result_type);  
  105.     }  
  106.   
  107.     function fetch_one_array($sql$type = '') {  
  108.         $qr = $this->query($sql$type);  
  109.         return $this->fetch_array($qr);  
  110.     }  
  111.   
  112.     function query($sql$type = '') {  
  113.         $this->link = &$this->link_rw;  
  114.         //判断是否select语句  
  115.         if($this->ro_exist && preg_match ("/^(\s*)select/i"$sql)){  
  116.             $this->link = &$this->link_ro;  
  117.         }  
  118.         $func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?  
  119.             'mysql_unbuffered_query' : 'mysql_query';  
  120.         if(!($query = $func($sql$this->link)) && $type != 'SILENT') {  
  121.             $this->halt('MySQL Query Error'$sql);  
  122.         }  
  123.         $this->querynum++;  
  124.         return $query;  
  125.     }  
  126.   
  127.     function affected_rows() {  
  128.         return mysql_affected_rows($this->link);  
  129.     }  
  130.   
  131.     function error() {  
  132.         return (($this->link) ? mysql_error($this->link) : mysql_error());  
  133.     }  
  134.   
  135.     function errno() {  
  136.         return intval(($this->link) ? mysql_errno($this->link) : mysql_errno());  
  137.     }  
  138.   
  139.     function result($query$row) {  
  140.         $query = @mysql_result($query$row);  
  141.         return $query;  
  142.     }  
  143.   
  144.     function num_rows($query) {  
  145.         $query = mysql_num_rows($query);  
  146.         return $query;  
  147.     }  
  148.   
  149.     function num_fields($query) {  
  150.         return mysql_num_fields($query);  
  151.     }  
  152.   
  153.     function free_result($query) {  
  154.         return mysql_free_result($query);  
  155.     }  
  156.   
  157.     function insert_id() {  
  158.         return ($id = mysql_insert_id($this->link)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);  
  159.     }  
  160.   
  161.     function fetch_row($query) {  
  162.         $query = mysql_fetch_row($query);  
  163.         return $query;  
  164.     }  
  165.   
  166.     function fetch_fields($query) {  
  167.         return mysql_fetch_field($query);  
  168.     }  
  169.   
  170.     function version() {  
  171.         return mysql_get_server_info($this->link);  
  172.     }  
  173.   
  174.     function close() {  
  175.         return mysql_close($this->link);  
  176.     }  
  177.   
  178.     function halt($message = ''$sql = '') {  
  179.         $dberror = $this->error();  
  180.         $dberrno = $this->errno();  
  181.         echo "<div style=\"position:absolute;font-size:11px;font-family:verdana,arial;background:#EBEBEB;padding:0.5em;\">  
  182.                 <b>MySQL Error</b><br>  
  183.                 <b>Message</b>: $message<br>  
  184.                 <b>SQL</b>: $sql<br>  
  185.                 <b>Error</b>: $dberror<br>  
  186.                 <b>Errno.</b>: $dberrno<br>  
  187.                 </div>";  
  188.         exit();  
  189.     }  
  190. }  
  191.   
  192. ?>  

 调用方法

Java代码   收藏代码
  1. <?php  
  2. /**************************************** 
  3. *** mysql-rw-php version 0.1 @ 2009-4-16 
  4. *** code by hqlulu#gmail.com 
  5. *** http://www.aslibra.com 
  6. *** http://code.google.com/p/mysql-rw-php/ 
  7. *** code modify from class_mysql.php (uchome) 
  8. ****************************************/  
  9.   
  10. require_once('mysql_rw_php.class.php');  
  11.   
  12. //rw info  
  13. $db_rw = array(  
  14.     'dbhost'=>'www.aslibra.com',  
  15.     'dbuser'=>'aslibra',  
  16.     'dbpw'=>'www.aslibra.com',  
  17.     'dbname'=>'test'  
  18. );  
  19.   
  20. $db_ro = array(  
  21.     array(  
  22.         'dbhost'=>'www.aslibra.com:4306',  
  23.         'dbuser'=>'aslibra',  
  24.         'dbpw'=>'www.aslibra.com'  
  25.     )  
  26. );  
  27.   
  28. $DB = new mysql_rw_php;  
  29.   
  30. //connect Master  
  31. $DB->connect($db_rw[dbhost], $db_rw[dbuser], $db_rw[dbpw], $db_rw[dbname]);  
  32.   
  33. //Method 1: connect one server  
  34. $DB->connect_ro($db_ro[0][dbhost], $db_ro[0][dbuser], $db_ro[0][dbpw]);  
  35.   
  36. //Method 2: connect one server from a list by rand  
  37. $DB->set_ro_list($db_ro);  
  38.   
  39. //send to rw  
  40. $sql = "insert into a set a='test'";  
  41. $DB->query($sql);  
  42.   
  43. //send to ro  
  44. $sql = "select * from a";  
  45. $qr = $DB->query($sql);  
  46. while($row = $DB->fetch_array($qr)){  
  47.     echo $row[a];  
  48. }  
  49. ?>  
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7月前
|
存储 SQL 关系型数据库
数据库魔法师:使用ShardingSphere实现MySQL读写分离与分片指南跟着爆叔的节奏稳了!
数据库魔法师:使用ShardingSphere实现MySQL读写分离与分片指南跟着爆叔的节奏稳了!
66 0
|
5天前
|
SQL 存储 负载均衡
关系型数据库读写分离与主从复制
关系型数据库读写分离与主从复制
20 5
|
6月前
|
Java 关系型数据库 MySQL
数据库系列课程(04)-SpringBoot整合MySQL读写分离
数据库系列课程(04)-SpringBoot整合MySQL读写分离
75 0
|
6月前
|
SQL Oracle 关系型数据库
数据库系列课程(02)-MyCat读写分离
数据库系列课程(02)-MyCat读写分离
44 0
|
6月前
|
存储 Java 数据库连接
Spring Boot 配置主从数据库实现读写分离
Spring Boot 配置主从数据库实现读写分离
202 0
|
8月前
|
负载均衡 算法 关系型数据库
ShardingSphere数据库读写分离
最近这段时间来经历了太多东西,无论是个人的压力还是个人和团队失误所带来的损失,都太多,被骂了很多,也被检讨,甚至一些不方便说的东西都经历了,不过还好,一切都得到了解决,无论好坏,这对于个人来说也是一种成长吧,事后自己也做了一些深刻的检讨,总结为一句话“挫败使你难受,使你睡不着觉,使你痛苦,不过最后一定会使你变得成熟,变得认真,变得负责”,每次面临挫败,我都会告诉自己,这不算什么,十年之后,你回过头来看待这件事的时候,你一定会觉得,这算什么屁事。
74 0
|
10月前
|
负载均衡 数据库
关于数据库读写分离
数据库读写分离是一种常用的数据库架构设计方式,主要目的是提高数据库的性能和可伸缩性。在传统的单节点数据库中,所有的读写操作都集中在一个节点上,容易造成性能瓶颈和单点故障。而通过读写分离,可以将读操作和写操作分别分配到不同的节点上,从而提高数据库的吞吐量和并发处理能力。
171 0
|
10月前
|
Cloud Native 关系型数据库 分布式数据库
阿里云最新产品手册——阿里云核心产品——云原生关系型数据库PolarDB——读写分离
阿里云最新产品手册——阿里云核心产品——云原生关系型数据库PolarDB——读写分离自制脑图
74 1
|
11月前
|
SQL 前端开发 数据库
解决读写分离主从数据库之间数据不同步的问题 Slave_SQL_Running: No slave_io_running:no
解决读写分离主从数据库之间数据不同步的问题 Slave_SQL_Running: No slave_io_running:no
90 0
|
11月前
|
SQL 关系型数据库 MySQL
读写分离的数据库相连接步骤
读写分离的数据库相连接步骤
82 0
读写分离的数据库相连接步骤