ubuntu 14.04 mysql Atlas 读写分离 环境配置安装

09 Mar 2016 Category: Developer

Atlas 是Qihoo 360, Web平台部基础架构团队在mysql_proxy基础上开发维护开发的一款mysql 中间件,360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。更多mysql 中间件可以参考 http://www.guokr.com/blog/475765/.

Altas的一些新特性:

  • 1.主库宕机不影响读
  • 2.通过管理接口,简化管理工作
  • 3.实现读写分离
  • 4.实现分表 (1)需带有分表字段。 (2)支持SELECT、INSERT、UPDATE、DELETE、REPLACE语句。 (3)支持多个子表查询结果的合并和排序。 (4)子表必须在同一台DB的同一个database里且所有的子表必须事先建好,Atlas没有自动建表的功能。

注意: Altas 不涉及数据主从同步,需要自己配置mysql 主从同步

mysql主从同步配置

mysql 主从同步配置是基于二进制日志进行的,因此需要开启数据库二进制日志。 查看是否开启二进制日志,可以进入mysql之后,执行SHOW BINARY LOGS;如果执行该 语句之后提示错误,则需要在my.cnf文件中的[mysqld]下添加

log-bin=mysql-bin #开启二进制日志 log-bin = /var/log/mysql/mysql-replication.log #指定二进制日志文件,必须

同时开启二进制日志,还需要注释skip-external-locking

在master数据库中,my.cnf文件配置:

server-id = 1 # 主库设置1
log-bin=mysql-bin #开启二进制日志
binlog-do-db=yii #需要同步的数据库,多个,添加多条binlog-do-db=database
binlog-ignore-db=mysql #不要同步的数据库
log-bin = /var/log/mysql/mysql-replication.log
#skip-external-locking

配置文件修改后,还需要为从库提供一个登录master数据库的用户名和密码,用于同步数据。


 grant replication slave on *.* to 'salveuser'@'%' identified by 'password';

重启master mysql服务,进入mysql,SHWO MASTER STATUS;查看master 服务器状态


+--------------------------+----------+--------------+------------------+
| File                     | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+--------------------------+----------+--------------+------------------+
| mysql-replication.000002 |      333 |              |                  |
+--------------------------+----------+--------------+------------------+

在salva 数据库,my.cnf配置


server-id = 2 #从库编号,大于1,一直往上加
log-bin=mysql-bin #开启二进制日志
replicate-ignore-db=mysql#不要同步的数据库
replicate-do-db=yii #开启二进制日志
log-bin = /var/log/mysql/mysql-replication.log
#skip-external-locking

在salve 数据mysql中执行下列sql语句,


CHANGE MASTER TO MASTER_HOST='master host',
MASTER_USER='salveuser',
MASTER_PASSWORD='111111',
MASTER_LOG_FILE='mysql-replication.000002',
MASTER_LOG_POS=333;

重启master mysql服务,进入mysql,start salve; show salve status\g;salve 服务器状态, 确认从服务器连接上主服务器。

Altas 安装配置

ubuntu 下载Atlas-2.2-debian7.0-x86_64.deb,下载之后,执行dpkg -i Atlas-2.2-debian7.0-x86_64.deb。 配置文件/usr/local/mysql-proxy/conf/test.conf

根据注释修改配置文件。默认注释的都不用修改,只有一项,#pwds = user1:+jKsgB3YAG8=, user2:GS+tr4TPgqc= 这一项如果不配置,无法登陆到数据库。

这里配置的是主库,从库的用户名以及密码,密码需要用/usr/local/mysql-proxy/bin/encrypt password 得到加密后的值

例如我的数据库用户名密码是 datauser , 111111

通过 /usr/local/mysql-proxy/bin/encrypt 111111得到的输出是kOVJsquUepY=

因此pwds=datauser:kOVJsquUepY=

配置完之后就可以使用了。

默认管理入口mysql -uusr -ppwd -P2345 -h127.0.0.1 对外sql接口 mysql -udatauser -p111111 -P1234 -h127.0.0.1 在程序中的数据库连接地址也采用对外接口的地址,Altas 会根据执行的sql语句分发到主库和从库当中

查看更多

http,tcp,udp协议

07 Mar 2016 Category: 基础

  • tcp协议是面向连接的传输层网络协议
  • tcp数据传输之前需要与接收方建立连接,进行三次握手之后才可以传输数据
  • tcp传输是可靠的,因为数据传输之前,发送接收方需要建立连接,进行数据传输同步,应用于大量数据传输的场景,传输速度慢
  • tcp连接是有状态的,长连接,除非网络中断或主动断开,连接才会中断
  • tcp,客户端向服务器发送syn(syn=j)进入SYN_SEND状态,服务器回复ACK(ack=j+1),同时发送SYN(syn=k)进入SYN_RECV状态,客户端发送ACK(ack=k+1),进入ESTABLISTION状态

udp协议

  • udp也是属于传输层网络协议
  • udp协议是非面向连接的,传输数据之前不需要与接收方建立连接
  • udp传输不可靠,应用于少量数据传输的场景,传输速度快

http协议

  • http协议是建立在tcp协议基础之上的应用层网络协议
  • http连接是无状态的,短连接,Http是一个基于请求/响应模式的、无状态的协议,每次请求完之后,连接就关闭
  • http连接,请求-响应式消息发送,服务器数据需要客户端请求才能发送到客户端。

HTTP的Request/Response:

先看Request 消息的结构,Request 消息分为3部分

  • 第一部分叫Request
    GET http://www.cnblogs.com/ HTTP/1.1
    

    Request line 指明请求方式,请求地址,以及http协议版本

  • 第二部分叫Request header

Accept: text/html 指明浏览器端可以接受的媒体类型,Accept: / 代表浏览器可以处理所有类型

Referer:http://translate.google.cn/?hl=zh-cn&tab=wT 提供了Request的上下文信息的服务器,告诉服务器我是从哪个链接过来的

Accept-Language: en-us 作用: 浏览器申明自己接收的语言。

Content-Type: application/json 作用: 浏览器申明请求数据的格式。

Accept-Encoding: gzip 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩

User-Agent 告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本

Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭, 如果close,则请求之后立即关闭

Content-Length:888 作用:发送给HTTP服务器数据的长度。

Host(发送请求时,该报头域是必需的) 请求报头域主要用于指定被请求资源的Internet主机和端口号,它通常从HTTP URL中提取出来的

  • 第二部分叫Response

第一部分叫request line, 第二部分叫request header,第三部分是body

request line:协议版本、状态码、message

  • 第二部分叫Response header

    Location响应报头域用于重定向接受者到一个新的位置。Location响应报头域常用在更换域名的时候。 Server响应报头域包含了服务器用来处理请求的软件信息。与User-Agent请求报头域是相对应的。 Content-Encoding用于记录文档的压缩方法 Content-Language实体报头域用于指明实体正文的长度,以字节方式存储的十进制数字来表示。 Content-Type实体报头域用语指明发送给接收者的实体正文的媒体类型 Last-Modified实体报头域用于指示资源的最后修改日期和时间。 Expires实体报头域给出响应过期的日期和时间。

  • http code
"200" : OK

"201" : Created 已创建

"202" : Accepted 接收

"203" : Non-Authoritative Information 非认证信息

"204" : No Content 无内容

"205" : Reset Content 重置内容

"206" : Partial Content 部分内容

重定向

"300" : Multiple Choices 多路选择

"301" : Moved Permanently  永久转移

"302" : Found 暂时转移

"303" : See Other 参见其它

"304" : Not Modified 未修改

"305" : Use Proxy 使用代理

"307" : Temporary Redirect

客户方错误

"400" : Bad Request 错误请求

"401" : Unauthorized 未认证

"402" : Payment Required 需要付费

"403" : Forbidden 禁止

"404" : Not Found 未找到

"405" : Method Not Allowed 方法不允许

"406" : Not Acceptable 不接受

"407" : Proxy Authentication Required 需要代理认证

"408" : Request Time-out 请求超时

"409" : Conflict 冲突

"410" : Gone 失败

"411" : Length Required 需要长度

"412" : Precondition Failed 条件失败

"413" : Request Entity Too Large 请求实体太大

"414" : Request-URI Too Large 请求URI太长

"415" : Unsupported Media Type 不支持媒体类型

"416" : Requested range not satisfiable

"417" : Expectation Failed

服务器错误

"500" : Internal Server Error 服务器内部错误

"501" : Not Implemented 未实现

"502" : Bad Gateway 网关失败

"503" : Service Unavailable

"504" : Gateway Time-out 网关超时

"505" : HTTP Version not supported  HTTP版本不支持

查看更多

php 设计模式 一

24 Feb 2016 Category: 基础

程序运行期间只有一个实例对象。单例模式类似于全局变量,在整个应用运行期间,共同操 作通一个对象。

class App{
    public static $appInstance;

    private $name;


    public static function getInstance()
    {
        if(App::$appInstance == null)
        {
            App::$appInstance = new App();
        }
        return App::$appInstance;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }
}

使用

$app = App::getInstance();
$app->setName('news');
echo $app->name;

##2.工厂模式

通过给工厂类指定不同的创建需求创建不同的类实例;

class People{
    function __construct($sex)
    {
        switch($sex){
            case 'male':
                return new Male();
            case 'female':
                return new Female();
        }
    }
}

class Male{
    public $sex = 'male';
}

class Female{
    public $sex = 'female';
}

使用:

$male = new People('male');
$female = new People('female');

##3.观察者模式

观察者模式是一个对象被多个对象观察(订阅),当这个被观察者对象改变时需要通知订阅者

class Subject{
    public $message;
    public $observes = [];
    /**
     * 被观察对象
     */
    public function addObserve($observe)
    {
        if(!in_array($observe,$this->observes))
        {
            $this->observes[] = $observe;
        }
    }

    public function deleteObserve($observe)
    {
        $index = array_search($observe,$this->observes);
        if($index !== false)
        {
            unset($this->observes[$index]);
        }
    }

    private function notifyObserve()
    {
        foreach($this->observes as $observe)
        {
            $observe->notify($this);
        }
    }

    public function setMessage($message)
    {
        $this->message = $message;
        $this->notify();
    }
}

class ObserveNews()
{
    public function notify($subject)
    {
        //TO-DO something
        echo 'news new message '.$subject->message;
    }
}

class ObserveWeibo()
{
    public function notify($subject)
    {
        //TO-DO something
        echo 'weibo new message '.$subject->message;
    }
}

使用

$subject = new Subject();
$subject->addObserve(new ObserveNews());
$subject->addObserve(new ObserveWeibo());
$subject->setMessage('a');//这里将会输出两条数据news new message a,weibo new message a;

查看更多

正则贪婪与非贪婪

19 Feb 2016 Category: 基础

贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配 成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少 的匹配。

属于贪婪模式的量词,也叫做匹配优先量词,包括:

"{m,n}"、"{m,}"、"?"、"*"和"+"。

在一些使用NFA引擎的语言中,在匹配优先量词后加上”?”,即变成属于非贪婪模式的量词, 也叫做忽略优先量词,包括:

"{m,n}?"、"{m,}?"、"??"、"*?"和"+?"

区别

以字符串<div>test4567</div><div>other</div>为例

表达式<div>.*</div>,匹配的字符串<div>test4567</div><div>other</div> 表达式<div>.*?</div>,匹配的字符串<div>test4567</div> 表达式<div>\w*(\d+)</div>匹配字符串<div>test4567</div>,$1 的值7 表达式<div>\w*?(\d+)</div>匹配字符串<div>test4567</div>,$1 的值4567

说明

贪婪模式,是尽可能多的匹配数据。如果后面有其他的表达式,或者再往后会导致整体匹配 失败,则进行回溯。

非贪婪模式,尽可能少的匹配数据,在保证整体匹配成功的情况下,匹配最少的数据,回溯 多次,确保匹配结果最小。

查看更多

支付宝自动咻一咻python脚本

03 Feb 2016 Category: script

一道过年,各种红包。支付宝的红包虽说今年换了玩法,不过还是点,点,点。这种最适合的就是采用自动化测试那一套。 因此,空闲时看了看android的自动化测试者方面的东西,采用Appium python-client,写了一个测试脚本,对支付宝进行 测试,实现咻一咻自动化。

代码地址github

查看更多

gitbook 安装

22 Jan 2016 Category: tools

gitbook 是github中比较流行用来记录分享的工具,也是写工作文档非常好的工具。 因此打算折腾一番。

GitBook Github地址给出的安装使用步骤:

npm install gitbook-cli -g

gitbook inti

gitbook build

gitbook serve

如果没有墙,上面的步骤都没错!!!

  • 如果不采用国内镜像,install的时候回出现网络超时。
  • 如果使用alias安装的镜像,比如添加一个cnpm命令采用国内镜像,是可以安装,但是当 执行gitbook init命令的时候会自动执行install laste版本的gitbook。因此alias方式的国内 镜像会是的gitbook init失败

因此,最好是添加全局镜像 npm config set registry https://registry.npm.taobao.org

查看更多

sublime markdown preview 输出文档添加日期

20 Jan 2016 Category: tools

最近输出文档都是使用sublime 编辑markdown文件,然后用markdown preview 的方式输出html文件或者pdf。但是每次编辑完之后总是需要手动添加一个更新 日期,未免有些麻烦,而且有时候修改急,会有遗忘的时候。因此想要让sublime 自动为我的文档添加一个update time。

sublime markdown preview插件都是python语言,修改起来还是比较方便。跟踪代码, 发现1191行有save_utf8(tmp_fullpath, html);这里的html内容就是从网络获取之后的 一个html内容。因此如果想要添加内容就要在内容被写入缓存前添加。

但是,有些文件确实不需要添加更新日期,所以还需要为插件添加一项配置项,在插件 的配置文件中添加add_update_time配置项,在MerkdownPreview.py文件中,采用

if settings.get('add_update_time',True)

获取插件配置

因此修改内容为:

if settings.get('add_update_time',True):
    html += "<p>update time "+time.strftime( '%Y-%m-%d %X', time.localtime() )+"</p>"

查看更多

js 脑补

06 Jan 2016 Category: Javascript

js的变量作用域,根据不同的定义位置分为全局变量以及局部变量。同事, 任何没有用var定义的变量都是全局变量。如果没有局部变量,则寻找全局变量。 但是需要注意一点,函数域优于全局域,当变量调用语句在函数域内,同时函数域中也存在 局部变量,则使用的是局部变量,不管调用时,变量是否定义。


var a = 123;//全局变量
function test(){
    alert(a);//弹出undefined,因为此时局部变量a还为定义;
    var a = 1;
    alert(a);//弹出1;
}

如果把函数中var a = 1;注释掉,则会弹出两次123

函数和闭包


function test()
{
    var a = [];
    var i = 0;
    for(i=0;i<3;i++)
    {
        a[i] = function(){
            return i;
        }
    }
    return a;
}

var f = test();
console.log(f[0]);//输出3
console.log(f[1]);//输出3
console.log(f[2]);//输出3

控制台输出 3,3,3

说明: a[i],这里的i是循环的时候就已经确定了。


function(){
    return i;
}

这里的i是test函数执行完之后,即循环三次之后的i,因此i=3;

如果想要是想a[0] = 0;需要在函数定义的时候,将i作为参数传入函数中。


function test()
{
    var a = [];
    var i = 0;
    for(i=0;i<3;i++)
    {
        a[i] = (function(x){
            return x;
        })(i)
    }
    return a;
}

var f = test();
console.log(f[0]);//输出0
console.log(f[1]);//输出1
console.log(f[2]);//输出2

查看更多