生命之中的最大错误在于:终日担心犯错误。— 爱尔伯特·哈伯德 (Elbert Hubbard 1856-1915),《笔记》
分页: 2/5 第一页 上页 1 2 3 4 5 下页 最后页 [ 显示模式: 摘要 | 列表 ]
案例:

希望增加一台只读的从数据库,已经有主从配置。
这里就不必停止主服务器做主从了,从服务器拷贝一份就直接能够处理。

方法:

先停止从服务器的同步 slave stop
这样,从服务器就是处于一个没有更新的且只读的状态,如果没有inodb类型的,那整个数据库文件夹拷贝一份就可以了,我的配置文件在此文件夹里。
拷贝完毕,执行 slave start 继续同步。

启用另外一台:

把拷贝的那份放另外一个机器上运行,能够正常运行,没有太留意问题。
正常状态应该是在主服务器看到slave的进程的状态是:
引用
Has sent all binlog to slave; waiting for binlog to be updated

比较奇怪的是,我有三台slave,只有两个进程看的到,另外一台的进程看不到。
在另外一台上查看状态是
引用
Queueing master event to the relay log

还非常奇怪,一直都是这个状态,明显可以检查出来,数据更新延后了,半天时间过去了也这样。

问题所在:

想起来配置文件没有修改,server-id是一样的,这个可能是问题。
遂修改所有slave服务器为唯一的id,问题解决。
三个slave的进程都在主服务器进程,状态都是
引用
Has sent all binlog to slave; waiting for binlog to be updated
Tags:
最近在生产环境使用了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: ,
1 IP高可用性
可以靠keepalived来维持。

2 web高可用性
可以用proxy服务器的负载均衡分配,一般自带后端检查,可以是nginx,比较流行这个。

3 php运行
可以是fastcgi,也是可以实现负载均衡,能者多劳。

4 mysql
可以使用amoeba或者mysql-proxy,实现读写分离和负载均衡,重要的事情是主从配置和维护。
amoeba-mysql的安装使用和读写分离
Amoeba for Mysql 试用小结

5 数据缓存层
可以用memcached,速度要求低一点的可以用memcachedb,使用magent可以做代理,保持高可用性。
Nginx和memcached/memcachedb配合可以加速可缓存的访问。
memcached和magent的安装
memcachedb的缓存解决方案

6 nginx的proxy性能
可以使用自带的memcache加速,起文件缓存作用。
也许还可以使用同步文件到本地的方式,不经过cache服务器。

7 cache服务器
比如lighttpd+modcache,或者squid、varnish等。新出的modcache可以利用内存缓存,性能估计能高一些,只是用内存缓存居然不支持本地压缩了,需要改为后端处理gzip工作。
lighttpd的mod_cache缓存不了的问题

总体而言
要高可用性,必须有代理层,有了代理层才会解决单点故障。。。
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: ,
JSP一直用的不多,但最近还是有擦边了,记录一下艰难的使用mysql的过程。

要使用Mysql那肯定用到相应的mysql的jar包了,只是我比较笨,不太懂从哪里获得什么样的jar文件才能使用,所以只能靠点网上的经验了:

JSP连接mysql数据库攻略

05年的文章了,看来四年前的知识我现在都赶不上,可以跟着操作一下。

安装Mysql就不用说了,跟使用没有关系,先下载Mysql的jar文件:

JDBC驱动 mysql-connector-java-3.1.14.tar.gz
http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-3.1.14.tar.gz/from/pick

文件下载后,解压后有一个 mysql-connector-java-3.1.14-bin.jar 文件,这个就是我们需要的啦。

1 jar文件放在哪里?

这个对于不熟悉jsp的人而言,有点茫然,jsp怎么找jar文件的,查找顺序是怎么样的?等我知道具体细节再做笔记。今天只是小尝试了一下:

WEB-INF/lib/
Tomcat_dir/common/lib/
Tomcat_dir/shared/lib/
Java_dir/j2sdk1.4.2_15/lib/


我在这几个目录依次都放置了,可还提示无法找到相应的类,可怜了,重启tomcat后就可以了。
不服气,然后就倒着依次删掉,依次重启tomcat,尝试出还是放 common/lib/ 下稳妥,但居然放在 WEB-INF/lib/ 下无用,java真复杂,可惜没有时间细研究这个问题了。

2 代码怎么写?

参考上面的页面即可,这里也贴一下稍微整理过的代码:

<%@ page import="com.mysql.jdbc.Driver" %>
<%@ page import="java.sql.*" %>
<%

//Mysql
String driverName="com.mysql.jdbc.Driver";
String mysqlserver="www.aslibra.com";
String userName="aquan";
String userPasswd="aquan";
String dbName="aslibra";

Class.forName(driverName).newInstance();
String mysqlURL="jdbc:mysql://"+mysqlserver+"/"+dbName+"?user="+userName+"&password="+userPasswd;
Connection connection = DriverManager.getConnection(mysqlURL);
Statement statement = connection.createStatement();
String sql="SELECT * FROM usr";
ResultSet rs = statement.executeQuery(sql);
while(rs.next()) {
  out.print(rs.getString(1)+" ");
  out.print("|");
  out.print(rs.getString(2));
  out.print("<br>");
}
rs.close();
statement.close();
connection.close();

%>


真伤心,jsp里面使用这个还没有php里面使用方便,一直纳闷为什么insert会出错

sql="insert into usr set userID='1',nickName='aquan',website='http://www.aslibra.com/' ";
//out.print("<hr>"+sql);
statement.executeQuery(sql);


后来还是找到解法:

引用
The method executeQuery is designed for statements that
produce a single result set, such as SELECT statements.

The method executeUpdate is used to execute INSERT, UPDATE,
or DELETE statements and also SQL DDL (Data Definition Language)
statements like CREATE TABLE, DROP TABLE, and ALTER TABLE....


来自: http://www.javaworld.com.tw/jute/post/view?bid=6&id=60810&tpg=1&ppg=1&sty=1&age=0#60810
原出处: http://java.sun.com/j2se/1.4.2/docs/guide/jdbc/getstart/statement.html#1003674

代码小修改即可:

sql="insert into usr set userID='1',nickName='aquan',website='http://www.aslibra.com/' ";
//out.print("<hr>"+sql);
statement.executeUpdate(sql);


真搞不懂,就这么一个语句在php里面就统一成 mysql_query 就成了,多方便啊~~
Tags: ,
分页: 2/5 第一页 上页 1 2 3 4 5 下页 最后页 [ 显示模式: 摘要 | 列表 ]

阅读推荐

服务器相关推荐

开发相关推荐

应用软件推荐