利用mysql的amoeba实现主从和读写分离

1.主从

主从数据库是通过mysql自带的功能完成的,mysql版本是5.7.7
主数据库:192.168.1.121
从数据库:192.168.1.122
统一主从数据的远程登陆账户密码,因为后面amoeba完成读写分离的需要这样
我就用root了,密码为123456
在主数据的配置文件的[mysqld]下面添加

#主数据库配置
log-bin=mysql-bin       #打开mysql二进制日志
server-id=1             #设置mysql_id主从不能相同,不能和其他的服务器相同
binlog-do-db=test       #设置二进制日志记录的库,多个数据库像这样复制一份就好了,所有数据库都需要记录,就去掉这一项
#binlog-do-db=test1        
binlog-ignore-db=mysql  #设置二进制日志不记录的库
sync_binlog=1

从数据库配置
在从数据库的配置文件的

#mysql主从配置 从数据库配置
log-bin=mysql-bin
server-id=2
replicate-do-db=test          #设置同步的库
replicate-ignore-db=mysql     #设置不同步的库
log-slave-updates             #同步后记录二进制日志
slave-skip-errors=all
sync_binlog=1
slave-net-timeout=60

在主数据库里面获得master的数据

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000002  #这个会用到
         Position: 913               #这个会用到
     Binlog_Do_DB: test
 Binlog_Ignore_DB: mysql
Executed_Gtid_Set: 
1 row in set (0.00 sec)

在从数据库里面设置主数据库

mysql>stop slave;
mysql>change master to master_host='192.168.1.121',master_user='root',
master_password='123456',master_log_file='mysql-bin.000002',master_log_pos=913;
mysql>start slave;

在从数据库查看是否成功,标记的两个都是yes就是好了

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.121
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000002
          Read_Master_Log_Pos: 375
               Relay_Log_File: 192-relay-bin.000004
                Relay_Log_Pos: 541
        Relay_Master_Log_File: mysql-bin.000002
             Slave_IO_Running: Yes       #这个是yes
            Slave_SQL_Running: Yes       #这个是yes
              Replicate_Do_DB: test
          Replicate_Ignore_DB: mysql
...后面太长,省略了

我在这里碰到一个问题

mysql> show slave status\G;
*************************** 1. row ***************************
...前面太长省略
             Slave_IO_Running: No
...省略
                Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
...省略

因为我是直接复制的虚拟机,所以mysql的uuid相同了,把数据目录的auto.conf文件删除就ok了

2.读写分离

下载jdk我是下载地址
根据版本下载,我下载的是 jdk-6u45-linux-x64.bin
安装

安装
#mkdir/usr/java/
//新建一个文件夹,把安装包给拷贝到这个文件夹下面
#chmod755jdk-6u25-linux-i586.bin
//给文件授权#
./jdk-6u25-linux-i586.bin//解压文件
配置jdk环境变量
#vim/etc/profile
//打开文件
在文件最后添加如下内容
######forjava
export JAVA_HOME=/usr/java/jdk1.6.0_45
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
#######
#source/etc/profile//重新执行一遍(有必要)
=============================================================================
测试JDK和AMOEBA_HOME是否设置成功
#java-version
//查看jdk版本验证java环境变量是否配置成功
javaversion"1.6.0_45"

安装amoeba

下载Amoeba并安装
#mkdir/usr/local/amoeba///创建文件夹
#cd/usr/local/amoeba///打开说创建的文件夹
#wget
http://sourceforge.net/projects/amoeba/files/Amoeba%20for%20mysql/2.x/amoeba-mysql-binary-2.1.0-RC5.tar.gz/download
//下载Amoeba文件
#md5sumamoeba-mysql-binary-2.1.0-RC5.tar.gz//校验MD5一般不需要
44f6708652a46f28a95338f35f5d4083amoeba-mysql-binary-2.1.0-RC5.tar.gz
#chmod755amoeba-mysql-binary-2.1.0-RC5.tar.gz//文件授权
#tar-zxvfamoeba-mysql-binary-2.1.0-RC5.tar.gz/解压文件
配置Amoeba环境变量
#vim/etc/profile
//打开文件
在结尾添加如下内容###amoeba
export AMOEBA_HOME=/usr/local/amoeba/
export PATH=$PATH:$AMOEBA_HOME/bin#######

配置 AMOEBA配置文件
配置mysql服务器的信息

vi /usr/local/amoeba/conf/dbServers.xml

...这一部分不需要改省略掉...
 <dbServer name="abstractServer" abstractive="true">
                <factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
                        <property name="manager">${defaultManager}</property>
                        <property name="sendBufferSize">64</property>
                        <property name="receiveBufferSize">128</property>
                        #配置这部分的数据库服务器的mysql的账号和密码,端口
                        <!-- mysql port -->
                        <property name="port">3306</property>

                        <!-- mysql schema -->
                        <property name="schema">test</property>

                        <!-- mysql user -->
                        <property name="user">root</property>


                        <property name="password">123456</property>

                </factoryConfig>
...这一部分不需要改省略掉...
#以下面的格式设置好mysql服务器的ip,设置好别名,别名不能一样,在其他地方会用到
<dbServer name="Master"  parent="abstractServer">
               <factoryConfig>
                       <!-- mysql ip -->
                       <property name="ipAddress">192.168.1.121</property>
               </factoryConfig>
</dbServer>

<dbServer name="Server1"  parent="abstractServer">
        <factoryConfig>
                <!-- mysql ip -->
                <property name="ipAddress">192.168.1.122</property>
        </factoryConfig>
</dbServer>

<dbServer name="Server2"  parent="abstractServer">
        <factoryConfig>
                <!-- mysql ip -->
                <property name="ipAddress">192.168.1.123</property>
        </factoryConfig>
</dbServer>
#这个比较特殊,用作轮询
<dbServer name="multiPool" virtual="true">
       <poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
               <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
               #这个属性设置成1,代表的就是轮询,
               <property name="loadbalance">1</property>
               <!-- Separated by commas,such as: server1,server2,server1 -->
                #这个选项里面填上面几个设置的名字,会依次轮询填进去的服务器
               <property name="poolNames">Server1,Server2</property>
       </poolConfig>
</dbServer>
...这一部分不需要改省略掉...

配置amoeba的信息

...这一部分不需要改省略掉...
#下面这部分设置连接amoeba的账号密码,通过mysql连接mysql的时候就填这里设置的账号的密码
<property name="authenticator">
        <bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">

                <property name="user">root</property>

                <property name="password">123456</property>

                <property name="filter">
                        <bean class="com.meidusa.amoeba.server.IPAccessController">
                                <property name="ipFile">${amoeba.home}/conf/access_list.conf</property>
                        </bean>
                </property>
        </bean>
</property>
...这一部分不需要改省略掉...
下面这部分就是设置读写分离和负载均衡的
<queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
        <property name="ruleLoader">
                <bean class="com.meidusa.amoeba.route.TableRuleFileLoader">
                        <property name="ruleFile">${amoeba.home}/conf/rule.xml</property>
                        <property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>
                </bean>
        </property>
        <property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
        <property name="LRUMapSize">1500</property>
        #默认连接的数据库
        <property name="defaultPool">Master</property>
        #DML操作的数据库,填主数据库就行了
        <property name="writePool">Master</property>
        #填设置了轮询的dbServer的名称
        <property name="readPool">multiPool</property>

        <property name="needParse">true</property>
</queryRouter>

这样就ok了,在这一步碰到问题

#amoeba start
The stack size specified is too small, Specify at least 160k
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

解决方法:

# vim amoeba
#修改58行的Xss参数:
DEFAULT_OPTS="-server -Xms1024m -Xmx1024m -Xss128k"
#修改为:
DEFAULT_OPTS="-server -Xms1024m -Xmx1024m -Xss256k"

参考:http://wenku.baidu.com/view/848d692e2e3f5727a4e96218.html?qq-pf-to=pcqq.c2c
http://blog.itpub.net/90618/viewspace-774894/

提高PHP速度的几种办法

PHP,是英文超级文本预处理语言Hypertext Preprocessor的缩写。PHP 是一种 HTML 内嵌式的语言,是一种在服务器端执行的嵌入HTML文档的脚本语言,语言的风格有类似于C语言,被广泛的运用。下面介绍提高PHP速度的方法。
用单引号来包含字符串要比双引号来包含字符串更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中说echo是语言结构,不是真正的函数,故把函数加上了双引号)。
1、如果能将类的方法定义成static,就尽量定义成static,它的速度会提升将近4倍。
2、$row[’id’] 的速度是$row[id]的7倍。
3、echo 比 print 快,并且使用echo的多重参数(译注:指用逗号而不是句点)代替字符串连接,比如echo $str1,$str2。
4、在执行for循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用foreach代替。
5、注销那些不用的变量尤其是大数组,以便释放内存。
6、尽量避免使用__get,__set,__autoload。
7、require_once()代价昂贵。
8、include文件时尽量使用绝对路径,因为它避免了PHP去include_path里查找文件的速度,解析操作系统路径所需的时间会更少。
9、如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于time()。
10、函数代替正则表达式完成相同功能。
11、str_replace函数比preg_replace函数快,但strtr函数的效率是str_replace函数的四倍。
12、如果一个字符串替换函数,可接受数组或字符作为参数,并且参数长度不太长,那么可以考虑额外写一段替换代码,使得每次传递参数是一个字符,而不是只写一行代码接受数组作为查询和替换的参数。
13、使用选择分支语句(译注:即switch case)好于使用多个if,else if语句。
14、用@屏蔽错误消息的做法非常低效,极其低效。
15、打开apache的mod_deflate模块,可以提高网页的浏览速度。
16、数据库连接当使用完毕时应关掉,不要用长连接。
17、错误消息代价昂贵。
18、在方法中递增局部变量,速度是最快的。几乎与在函数中调用局部变量的速度相当。
19、递增一个全局变量要比递增一个局部变量慢2倍。
20、递增一个对象属性(如:$this->prop++)要比递增一个局部变量慢3倍。
PHP的优点之一是速度很快,对于一般的网站应用,可以说是已经足够了。不过如果站点的访问量很高、带宽窄或者其它的因素令服务器产生性能瓶颈的时候,提高速度是我们首先想到的。希望本文对你有帮助。

php闭包

<?php
//提到闭包就不得不想起匿名函数,
//也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它。声明一个匿名函数是这样:
$func=function ($value='')
{
    echo "test!!!";
};
$func();//输出test!!!
?>

闭包函数当成变量使用

<?php
//闭包函数当作变量来使用
$func_1=function ($value='')
{
    echo "This is func_1!!!";
};
$func_2=function ($value='')
{
    echo "This is func_2!!!";
};
//闭包函数当作变量来使用
function test($value){
    $value();
}
test($func_1);//输出  This is func_1!!!
test($func_2);//输出  This is func_2!!!
//或者直接传递
test(function ($value='')//输出  This is func_3!!!
{
    echo "This is func_3!!!";
});
?>

闭包函数使用外部变量:PHP在默认情况下,匿名函数不能调用所在代码块的上下文变量,而需要通过使用use关键字。
如下,会报错

<?php
//闭包函数当作变量来使用
$str='This is string';
$num=1;
$func_1=function ($value='')
{
    echo "This is func_1!!!";
    echo $str;//报错Notice: Undefined variable: str in D:\wamp\wamp\www\mytest\tp_ceshi.php on line <em>8</em>
    echo $num;//报错Notice: Undefined variable: num in D:\wamp\wamp\www\mytest\tp_ceshi.php on line <em>9</em>
};
$func_1();
?>
```php
如下
```php
<?php
//闭包函数使用外部变量
$str='This is string';
$num=1;
$func_1=function ($value='')use($str,$num)
{
    echo "This is func_1!!!";
    echo "<br/>";
    echo $str;
    echo "<br/>";
    echo $num;
};
$func_1();
//输出
This is func_1!!!
This is string
1
?>

闭包改变外部变量

<?php
//闭包函数使用外部变量
$str='This is string';
$num=1;
$func_1=function ($value='')use($str,$num)
{
    echo $num;
    $num++;
};
$func_1();
echo $num;
//输出结果: 1   1
?>

和一般函数一样,闭包函数不能改变外部变量的值,因为是值传递,想要改变外部变量的值,只需要在传递变量进去的时候在变量前加上"&"
php php

php发送get,post

转载自:http://blog.csdn.net/haha00217/article/details/7969504

一,用file_get_contents来发送get以get方式接受

<?php
$url='http://localhost/mytest/tset.php';
$html=file_get_contents($url);
var_dump($html);
?>

二, 用fopen打开url, 以get方式获取内容

<?php
$url='http://localhost/mytest/tset.php';
//php手册上说是把资源绑定到一个流上面,成功之后返回文件指针资源
$html=fopen($url, 'r');
//这个函数会返回当前协议文件中取得一些信息(php手册上这样说,我自己把这个理解成取得当前请求的一些信息,比如请求是否成功,服务器版本啊之类的信息)
var_dump(stream_get_meta_data($html));
$str='';
//因为$html是一个指针资源,不能直接输出,所以要使用下面的循环来取出,类似于从数据库取出资源
//循环,没到文件结尾就循环feof检测是否到达文件指针结尾
while (!feof($html)) {
    //从文件指针中读取后面设置的字节
    $str.=fgets($html,1024);
}
var_dump($str);
//关闭已经打开的文件指针,免得占用资源,感觉和mysql连接一样,不用的时候要关掉~~~
fclose($html);
?>

三,用file_get_contents函数,以post方式获取

<?php
$url='http://localhost/mytest/tset.php';
//要传递的参数
$data=array('boo'=>'bar');
//这个函数是可以把数组转换成boo=bar形式,现在参数很少所以没什么,但是参数多的话用这个函数很方便(应该是这个作用吧~~)
$data=http_build_query($data);
//http请求的参数,注意header项的值要用双引号,不然\r\n不会被解析成换行符,会影响传值,别的影响没遇到,不知道
$options=array(
    'http'=>array(
            'method'=>'POST',
            'header'=>"Content-type: application/x-www-form-urlencoded\r\n"."Content-Length: " . strlen($data) . "\r\n",
            'content' => $data
    )
);
//创建一个上下文资源流
$content=stream_context_create($options);
//发送请求第一个参数是文件位置,改成false和true没什么影响啊,第三个就是http请求头以及一些设置选项了
$html=file_get_contents($url,true,$content);
var_dump($html);
?>

四,用fsockopen函数
post

<?php
//@file phpinput_post.php
//要传递的参数
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788');
//应该是请求发送给接受者的实体正文类型
$http_entity_type = 'application/x-www-form-urlencoded';
//正文的长度
$http_entity_length = strlen($http_entity_body);
$host = '127.0.0.1';
$port = 80;
$path = 'http://localhost/mytest/tset.php';
//依次是,主机,端口,错误号,错误信息,过期时间,这步好像没发请求
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
    //写协议内容。。。页面地址
fputs($fp, "POST {$path} HTTP/1.1\r\n");
//主机
fputs($fp, "Host: {$host}\r\n");
//请求正文类型
fputs($fp, "Content-Type: {$http_entity_type}\r\n");
//正文长度
fputs($fp, "Content-Length: {$http_entity_length}\r\n");
//这个不知道....
fputs($fp, "Connection: close\r\n\r\n");
//发送的数据
fputs($fp, $http_entity_body . "\r\n\r\n");
$d='';
//取出数据
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
//关闭连接
fclose($fp);
//直接输出会输出http协议信息,所以做一些处理
//先从http协议中计算出正文的长度
preg_match('/Content-Length: (\d+)/', $d, $maths );
//var_dump($maths[1]);
//用字符串的总长度减去正文的长度就是http协议的长度了,再用substr截取就ok了
$d=substr($d,strlen($d)-(int)$maths[1]);
//输出请求结果
echo $d;
}
?>

get

<?php
//@file phpinput_post.php
//要传递的参数
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788');
$host = '127.0.0.1';
$port = 80;
$path = 'http://localhost/mytest/tset.php';
//依次是,主机,端口,错误号,错误信息,过期时间,这步好像没发请求
$fp = fsockopen($host, $port, $error_no, $error_desc, 10);
if ($fp) {
    //写协议内容。。。页面地址
fputs($fp, "GET {$path}?{$http_entity_body} HTTP/1.1\r\n");
//主机
fputs($fp, "Host: {$host}\r\n");
//这个不知道....
fputs($fp, "Connection: close\r\n\r\n");
$d='';
//取出数据
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
//关闭连接
fclose($fp);
//直接输出会输出http协议信息,所以做一些处理
//先从http协议中计算出正文的长度
preg_match('/Content-Length: (\d+)/', $d, $maths );
//var_dump($maths[1]);
//用字符串的总长度减去正文的长度就是http协议的长度了,再用substr截取就ok了
//$d=substr($d,strlen($d)-(int)$maths[1]);
//输出请求结果
echo $d;
}
?>

五,使用curl库,使用curl库之前,需要查看一下php.ini是否已经打开了curl扩展

<?php
//初始化一个curl回话(感觉就是实例化了一个对象。。)
$cu=curl_init();
$timeout=30;
//设置一个curl回话的传输选项,有很多选项可以设置,这里就不一一设置了
curl_setopt($cu, CURLOPT_URL, 'http://localhost/mytest/tset.php');
//设置值为"1"成功会返回请求页面的内容,设置为"0"成功会返回1
curl_setopt($cu, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($cu, CURLOPT_CONNECTTIMEOUT, $timeout);
$res=curl_exec($cu);
echo $res;
?>

$_POST,php://input,$_GET直接的区别

参考http://www.jb51.net/article/31317.htm

1, php://input 可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据。但是,一般GET方法提交数据 时,http request entity body部分都为空。
2,php://input 与$HTTP_RAW_POST_DATA读取的数据是一样的,都只读取Content-Type不为multipart/form-data的数据。


1,Coentent-Type仅在取值为application/x-www-form-urlencoded和multipart/form-data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST
2,PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA
3, 只有Coentent-Type不为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php://input,否则其它情况都会。填入的长度,由Coentent-Length指定。
4,只有Content-Type为application/x-www-data-urlencoded时,php://input数据才跟$_POST数据相一致。
5,php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini
6,PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。