最近在生产环境使用了amoeba,发现一些问题:

1 sql语句不支持,产生大量错误日志
2 有重复执行的迹象,发生数据重复插入到master,还不确定这问题是否amoeba的问题
3 读写分离会在master出现读进程

第二点,就目前的使用情况而言,amoeba还是很稳定的,只是不太清楚是什么问题,如果重复插入数据的问题不是amoeba产生的,那对于应用而言没有错误发生。

对于第一点和第三点,我觉得是这么一个过程:

1 读写分离时会分析sql语句
2 如果语句属于检查范围的则正常进行读写判断,读操作发送到writePool,写操作发送至readPool,未知的sql语句则发送至defaultPool
3 一般defaultPool和写操作是master,所以在master发现select语句很正常,肯定是判断不出来的语句

sql出现的问题比较多,在log里面有找到以下性质的语句错误记录:

1 TRUNCATE TABLE XXX
2 EXPLAIN XXX
3 SELECT * FROM xx FORCE INDEX (xx)
4 insert into xx values('\'test\'') 转义的单引号
5 order by rand()


希望amoeba可以正常运行,不产生第二点错误就很满意了。
对于读操作,使用amoeba肯定是不错。

另外,master重启可能导致主从同步会不太稳定,多个从服务器的话比较长的时间才能稳定下来。
比较经常出现“Queueing master event to the relay log”,slave进程都没有持续,可能导致更新不够及时。

@20100105 补充:以上可能是server-id的问题,参考这里
Tags: ,
amoeba真的是不错的稳定而灵活的数据库解决方案,阿里巴巴的技术陈思儒开始的一个开源项目,它是分布式数据库Proxy解决方案。

About Amoeba
引用
Amoeba(变形虫)项目,专注 分布式数据库 proxy 开发。座落与Client、DB Server(s)之间。对客户
端透明。具有负载均衡、高可用性、sql过滤、读写分离、可路由相关的query到目标数据库、可并发请
求多台数据库合并结果。
主要解决:
* 降低 数据切分带来的复杂多数据库结构
* 提供切分规则并降低 数据切分规则 给应用带来的影响
* 降低db 与客户端的连接数
* 读写分离
* 制定一种规则可支持DB线性扩容

目前在amoeba 框架上面已经实现了 amoeba for mysql.


找寻到amoeba是出于想要做读写分离,目前可以有三种解决方式:

1 程序修改mysql操作类
可以参考PHP实现的Mysql读写分离,阿权开始的本项目,以php程序解决此需求。
优点:直接和数据库通信,简单快捷的读写分离和随机的方式实现的负载均衡,权限独立分配
缺点:自己维护更新,增减服务器在代码处理

2 amoeba
参考官网:http://amoeba.meidusa.com/
优点:直接实现读写分离和负载均衡,不用修改代码,有很灵活的数据解决方案
缺点:自己分配账户,和后端数据库权限管理独立,权限处理不够灵活

3 mysql-proxy
参考 mysql-proxy
优点:直接实现读写分离和负载均衡,不用修改代码,master和slave用一样的帐号
缺点:字符集问题,lua语言编程,还只是alpha版本,时间消耗有点高

如果你不能安装软件来解决读写分离,那可以尝试阿权的项目解决思路。
如果你可以安装软件,那amoeba是不错的,mysql-proxy不太建议,目前只有alpha版本,效率还不太理想,amoeba目前在阿里巴巴是内部项目,正在生产环境使用的。

amoeba的安装使用

1 安装java环境,需要Java SE 1.5 或以上
2 配置xml文件

下载地址: http://www.sf.net/projects/amoeba
解压就可以使用的,顺便说一下,打包的习惯似乎不是太好,最好解压后是自己的文件夹

运行很简单 bin/amoeba 即可,后台运行 bin/amoeba &
如果没有配置JAVA_HOME,则会有如下提示:

[root@aslibra amoeba-mysql]# bin/amoeba
Error: JAVA_HOME environment variable is not set.


如果你是比1.5低,比如1.4的,运行会有错误提示:

[root@aslibra amoeba-mysql]# bin/amoeba
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/meidusa/amoeba/mysql/server/MysqlProxyServer (Unsupported major.minor version 49.0)
        at java.lang.ClassLoader.defineClass0(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:539)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
.....


安装配置java环境对于不玩java的人不太熟悉,我也不是行家,把自己的配置过程作一下分享:

首先根据你的操作系统下载相应的文件,比如jdk-1.5.0,文件下载地址:
http://java.sun.com/javase/downloads/index.jsp

下载回来的是bin文件,加执行属性,然后执行后就能有一个rpm文件,然后安装即可:

[root@aslibra amoeba-mysql]# rpm -ivh jdk-1_5_0_15-linux-i586.rpm
Preparing...                ########################################### [100%]
        package jdk-1.5.0_15-fcs is already installed


配置JAVA_HOME变量:

[root@aslibra amoeba-mysql]# cd /usr/java/
[root@aslibra java]# ll
total 16
drwxr-xr-x  8 root root 4096 Apr 27 17:50 j2sdk1.4.2_15
lrwxrwxrwx  1 root root   13 Apr 27 17:52 jdk -> j2sdk1.4.2_15
drwxr-xr-x  9 root root 4096 May 13 09:14 jdk1.5.0_15
[root@aslibra java]# rm jdk
rm: remove symbolic link `jdk'? y
[root@aslibra java]# ln -s jdk1.5.0_15/ jdk
[root@aslibra java]# ll
total 16
drwxr-xr-x  8 root root 4096 May 13 09:20 j2sdk1.4.2_15
lrwxrwxrwx  1 root root   12 May 13 09:21 jdk -> jdk1.5.0_15/
drwxr-xr-x  9 root root 4096 May 13 09:14 jdk1.5.0_15


可以编辑 /etc/profile以便启动时变量生效,末尾加上

##############  java  ###########

JAVA_HOME=/usr/java/jdk
PATH=$PATH:JAVA_HOME/bin
export JAVA_HOME PATH


依次运行此三句,配置好xml后,即可立刻使用amoeba:

[root@aslibra amoeba-mysql]# bin/amoeba
log4j:WARN log4j config load completed from file:/Data/apps/amoeba-mysql/conf/log4j.xml
log4j:WARN ip access config load completed from file:/Data/apps/amoeba-mysql/conf/access_list.conf
2009-05-13 09:22:04,306 INFO  net.ServerableConnectionManager - Server listening on /192.168.1.5:9306.


配置amoeba:

conf/amoeba.xml 配置mysql数据库,简单说明一下:

1 server节点定义amoeba为接受client访问的数据库,可以当作是mysql看待的,用户名和密码是访问时使用的,这个似乎不能定义多个用户名密码,也就是只有一个权限控制,这个对于多应用似乎不大方便。
2 dbServerList里面可以定义很多实际的mysql数据库,增加dbServer节点即可,这里的用户名密码是作为amoeba操作数据库使用的,要有足够权限。dbServer可以是虚拟的,比如要做负载均衡时可用定义多个数据库归属到此虚拟数据库。
3 queryRouter节点定义读写的分配情况,也就是读写该发往那个dbServer。

读写分离的配置示例片段:

<dbServerList>
  <dbServer name="master">
  ....
  </dbServer>
  <dbServer name="slave1">
  ....
  </dbServer>
  <dbServer name="slave2">
  ....
  </dbServer>
  <dbServer name="slave3">
  ....
  </dbServer>    
  <dbServer name="multiPool" virtual="true">
    <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
      <property name="loadbalance">1</property>
      <property name="poolNames">slave1,slave2,slave3</property>
    </poolConfig>
  </dbServer>
</dbServerList>  
<queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
  <property name="LRUMapSize">1500</property>
  <property name="defaultPool">master</property>
  <property name="writePool">master</property>
  <property name="readPool">multiPool</property>
</queryRouter>


另外一个需要修改一下的是 conf/log4j.xml,定义日志内容:

引用
在可用性测试已经完成的情况下,建议将log4j.xml 中关于日志输出level为debug的全部设置成warn或者error 级别。
日志是非常消耗系统性能的,在没有必要的情况下可以不使用debug。

参考:关于amoeba 性能测试注意的几点

不算复杂的处理就完成了amoeba的配置和使用了,更加复杂的应用请参考官网介绍资料:
amoeba 中文文档下载地址:http://amoeba.meidusa.com/amoeba.pdf
Tags: ,
记录长时间的查询很有必要,这个对检查问题发生的原因有很大帮助,因为一般是长时间的查询会导致排队严重或者导致表锁定。

在配置文件里面加上几句即可:

long_query_time = 2
log_slow_queries = slow_queries
#log_queries_not_using_indexes = true


看字面即可理解设置的含义了,设置多长时间算是长时间的查询,设置日志名称,最后是否记录没有使用索引的查询。

日志名称如果是用/开头的,要注意日志写入权限,否则会出错。用一个名称则会放置在数据库目录var内。
没有使用索引的查询可能会很多,如果有必要那可以记录,但日志会出现好多

分析日志主要是查找到哪些查询占用时间比较长,这样可以优化数据库和程序。

比如如下日志片段:
引用
# Time: 090511 11:57:19
# User@Host: user[password] @  [192.168.1.2]
# Query_time: 5  Lock_time: 0  Rows_sent: 10  Rows_examined: 414839
SELECT (XXXX省略) ORDER BY s.friendnum DESC LIMIT 0,10;


最简单的改善方案是给该表的 friendnum 字段加索引。

日志分析没有做过,可以参考一下别人写的工具介绍:五款常用mysql slow log分析工具的比较
Tags:
一直有一个数据库没有同步的,非常的奇怪。

1 重新做一次同步,其它数据库都同步正常,唯独此数据库不同步
2 在phpmyadmin上操作,是可以正常同步到slave

由此可以大概判断是程序上可能有点问题了,可能是使用上的问题。

程序是uchome1.5版本的,经过检查,是数据库操作是没有选择相应的数据库:

文件:uc_client/model/base.php

/**
* 实例化数据库类
*
*/
function init_db() {
  require_once UC_ROOT.'lib/db.class.php';
  $this->db = new db();
  $this->db->connect(UC_DBHOST, UC_DBUSER, UC_DBPW, '', UC_DBCHARSET, UC_DBCONNECT, UC_DBTABLEPRE);
}


上面居然强制传了空的数据库名称,所以导致程序没有操作选择数据库:
文件:uc_client/lib/db.class.php

function connect($dbhost, $dbuser, $dbpw, $dbname = '', $dbcharset = '', $pconnect = 0, $tablepre='', $time = 0) {
  //省略部分代码
  if($dbname) {
    mysql_select_db($dbname, $this->link);
  }

}


没有dbname,所以没有进行mysql_select_db操作导致master没有记录,从而没有参与同步到slave。
小修改即可:

$this->db->connect(UC_DBHOST, UC_DBUSER, UC_DBPW, UC_DBNAME, UC_DBCHARSET, UC_DBCONNECT, UC_DBTABLEPRE);


这样就修复了程序的错误,重新处理同步即可。
Tags: ,
在使用中的环境如何在尽量少影响的情况下做数据库转移,这个有很多问题需要注意的,需要考虑周全。
这次要转移的数据库是MyISAM,转移起来比较简单,但目标数据库是Master-Slave方式的,所以转移起来需要注意:

1 转移到Master时,Master-Slave的数据应该是一样的,否则会导致同步出问题
2 转移到Master时,切换时间尽可能短

转移过程大概有以下阶段:

1 导出当前数据库的数据
2 导入到新的数据库
3 更改连接数据库的方式

第一阶段有好多方式:

1 导出sql文件mysqldump
  适合数据不多而且有InnoDB的数据表的情况。
mysqldump -S /Data/mysqldb/3306/mysql.sock -uusername -ppassword aslibra>backup.sql
-S 是sock文件的位置

2 复制数据库mysqlhotcopy
  适合MyISAM数据表
mysqlhotcopy -S /Data/mysqldb/3306/mysql.sock -u username -p password --addtodest aslibra /backup/mysql/
-S 是sock文件的位置
--addtodest 是覆盖现有数据库文件
会复制一份在/backup/mysql/aslibra/XXX

3 停止数据库,直接复制文件
  适合懒人不怕停止服务的情况

第二阶段主要看你选择的第一阶段了:

1 导入sql文件
mysql -S /Data/mysqldb/3306/mysql.sock -uusername -ppassword aslibra<backup.sql

如果没有相应的数据库,需要创建
可以远程导入的,导入到Master数据库就可以了,slave会自动传输的
2 复制数据库文件
这里就简单的复制了,打包传输然后到目标数据库解压也就ok了
或者scp传输文件,NFS共享文件
Master和Slave都传输一样的文件,记得文件在目标服务器需要是mysql可读写的

第三阶段是在第二阶段完成后立刻做的,这里有一个快捷的方式来应对有很多PHP文件需要修改的情况:

假设原先的数据库的连接是 127.0.0.1 ,先修改为 mysqldb,然后在 /etc/hosts文件里面加一行指定
127.0.0.1 mysqldb

这样的好处是,转移数据库连接方式只是需要修改hosts文件即可一下子把所有数据库连接都修改了,无痛转移。。
但以上方法要求mysql端口要一致。
另外,如果没法修改为名称做连接,那可以启用mysql-proxy,做一下设置就可以了,详细可以查询相关资料
也可以使用rinted做端口代理应付转移的过渡期,参考rinetd

以上三种过渡方式设定后,再修改每个连接为新的服务器连接即可。
Tags:
分页: 3/8 第一页 上页 1 2 3 4 5 6 7 8 下页 最后页 [ 显示模式: 摘要 | 列表 ]

阅读推荐

服务器相关推荐

开发相关推荐

应用软件推荐