网易cetus初探--读写分离

Posted 破产DBA

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网易cetus初探--读写分离相关的知识,希望对你有一定的参考价值。

什么是cetus?

前段时间淘宝买了个贴纸,觉得这个飞上天的鲸鱼很漂亮,后来查到这货是“鲸鱼座”,在与网易女神确认了这货原来有个英文名字--“cetus”,于此便有了后来的cetus的测试与使用。

网易cetus初探--读写分离


cetus是由网易乐得DBA团队用C语言开发的一款mysql中间件,提供了读写分离和分库两个版本,应用程序可几乎不做修改透明的通过cetus访问数据库群集,实现数据库的高可用以及水平扩展。

笔者通过将近一周的深入体验,各种场景折腾,各种压力测试,发现这款中间件产品的是非常不错的, 在与cetus成员交流的过程也感受到了 :他们是一群对技术要求极致,乐于分享的团队,每每遇到问题,都能在第一时间得到解答,非常NICE! cetus团队没有止步在仅仅是对外宣讲cetus,他们也在用实际行动帮助用户使用落地,看产品好坏,很大一部分还需要看这个团队是否都有一致的方向及热情, 这勾起了我很大的兴趣,毕竟这样的太少了!最近一段时间加强了cetus测试工作,发现cetus有很多独特的地方,配置简单,日志详尽,可在线修改配置,对SQL类型支持多,在读写分离模式下几乎能在不修改应用的情况直接运行,能在硬件资源较小的情况下依然能稳定运行等等...总之这是一款可以信赖的产品。

cetus版本分为读写分离和分库版本,在安装,配置与使用上有些区别,本次测试使用的读写分离版本。

cetus读写分离能做什么

提到cetus就不得不提cetus读写分离版本能实现的主要功能了:

  • 连接池; 

    在Cetus启动时,使用默认用户自动创建到后端的连接,请求过来不需要临时建立连接并切换数据库,提升效率。

  • 读写分离; 

    cetus能结合sql解析,根据分流策略将查询发到后端的只读从库上,从而减少主库查询负载,提升系统性能,开启监控后,可以配置参数slave-delay-down和slave-delay-recover,自动将从库状态down或up,而不影响系统的整体可用性。

  • TCP流式; 

    这是cetus很大一个卖点,cetus对内存的需求很小,对于结果集比较大的查询,cetus采用tcp stream流式,不需要先缓存完整结果集才转发给客户端,以避免内存炸裂问题,降低内存消耗,提高性能。

  • 状态监控; 

    开启监控功能后,Cetus会定期和后端进行通信,检测后端数据库的存活状态和主从延迟时间等。可通过登录管理端口SELECT * FROM backends查看。

  • 动态修改cetus参数; 

    cetus开放了管理端口,可动态修改cetus各项参数,无需重启服务即可完成。


综上:通过cetus我们能实现数据库端的透明访问,并通过读写分离,从库状态自动启停来实现负载均衡及改善后端数据库高可用,让DBA省心,让开发无忧。

cetus架构图示

前端应用通过连接访问cetus群集(使用LVS实现,实际可考虑部署到数据库节点上),后端mysql可以使用MHA或MGR架构实现高可用,再通过cetus实现数据库的读写分离透明访问。

网易cetus初探--读写分离

cetus读写分离版本安装

  1. 安装前的准备工作

    • 修改linux 最大文件限制数:
      echo ulimit -n 65535 >>/etc/profile 
      source /etc/profile #加载修改后的profile 
      ulimit -n #显示65535,修改完毕!

  2. 安装依赖包
    yum install cmake gcc glib2-devel flex mysql-devel gperftools-libs -y

  3. 安装cetus

  • 下载安装包
    mkdir cetus cd cetus git clone https://github.com/Lede-Inc/cetus.git

  • 源码编译

mkdir build/ cd build/ CFLAGS='-g -Wpointer-to-int-cast' cmake ../ \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_INSTALL_PREFIX=/usr/local/cetus \ -DSIMPLE_PARSER=ON make install

注意事项及关键参数:

  1. cmake ../ 这里../是指上一层,如果指定错了将无法继续

  2. CFLAGS='-g -Wpointer-to-int-cast' 在可执行程序中包含标准调试信息,

  3. CMAKE_BUILD_TYPE变量可以选择生成 debug 版和或release 版的程序,

  4. CMAKE_INSTALL_PREFIX变量确定软件的实际安装目录的绝对路径,

  5. SIMPLE_PARSER变量确定软件的编译版本,设置为ON则编译读写分离版本,否则编译分库版本。

读写分离版本配置

后端数据库配置架构

本次仅做功能性验证,故在笔记本上创建了1个虚拟机,上面部署两个数据库实例做主从,同时cetus也运行在这个虚机上。

网易cetus初探--读写分离


由于cetus需要监控主从延迟时间,使用的方法是不停的在主库写入当前时间,然后到从库查询时间,比较时间差异,原理上类似pt-heart工具,在运行前需要创建对应的数据库及表,否则cetus的监控及从库自动上下线无法使用。

create database proxy_heart_beat;use proxy_heart_beat;
CREATE TABLE `tb_heartbeat` (  
`p_id` varchar(128) NOT NULL,  
`p_ts` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),  PRIMARY KEY (`p_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建cetus连接的而用户cetus_app,加上所有库的权限,特别注意别忘了把心跳表的权限也加上:

GRANT ALL PRIVILEGES ON `proxy_heart_beat`.* TO 'cetus_app'@'%'

cetus用户密码参数文件配置:users.json

此文件记录的是后端数据库连接使用的用户和密码,以及对应的cetus对外提供访问使用的密码

[root@mysql-node1 cetus]# cd /usr/local/cetus[root@mysql-node1 cetus]# cat conf/users.json
{        "users":        
         [{    
            "user": "cetus_app",
              "client_pwd":   "cauUAX123321",    
               "server_pwd":   "cauUAX123321"                }] }

cetus变量处理配置文件参数文件配置:variables.json

配置允许发送的值和静默处理的值,一般无需配置,默认即可

[root@mysql-node1 cetus]# cat conf/variables.json
{    "variables": [
        {            "name": "sql_mode",            
                     "type": "string-csv",            
                     "allowed_values":  ["STRICT_TRANS_TABLES",                                "NO_AUTO_CREATE_USER",                                "NO_ENGINE_SUBSTITUTION"]        },        {            "name": "connect_timeout",            
                     "type": "string",            
                     "allowed_values": ["*"],            
                     "silent_values": ["10", "100"]        }    ] }

cetus启动配置文件:proxy.conf

这是最关键的读写分离版本的启动配置文件,在启动Cetus时需要加载,关键的参数以及在以下代码中注明

[root@mysql-node1 cetus]# cat conf/proxy.conf

[cetus]

# 是否通过守护进程启动

daemon = true

 

# Loaded Plugins

plugins=proxy,admin

 

# 定义启动进程数量,建议配置成cpu核数

worker-processes=8

 

#启动tcp stream,无需等响应收完就发送给客户端

enable-tcp-stream= true

 

# cetus对外服务端口及后端主从数据库配置

proxy-address=0.0.0.0:6001

proxy-backend-addresses=10.231.34.195:3306

proxy-read-only-backend-addresses=10.231.34.196:3306

 

# cetus管理端口及用户名和密码

admin-address=0.0.0.0:7001

admin-username=admin

admin-password=admin123

 

#默认数据库,用户名

default-db=cetus

default-username=cetus_app

 

#初始连接池及最大连接池大小,需要注意的是这个参数是针对每1cetus进程而言的

#比如当前配置:8进程*50=400 意味着cetus一启动就需要申请400个连接

#最大连接配置:8进程*400=3200 意味着后端数据库至少要配置比3200还要多的数据库连接参数才不会报错

default-pool-size=50

max-pool-size=400

 

#自动减少空闲连接,后端连接最大存活时间默认是2小时,现修改为1小时

reduce-connections=true

max-alive-time=3600

 

#每个后端返回结果集的最大数量

max-resp-size=10485760

 

#慢查询日志阈值(毫秒)

long-query-time=1000

 

#读写比例,主库50%,从库50%(所有的从库一起算)

read-master-percentage=50

 

 

max-open-files= 65536

plugin-dir=lib/cetus/plugins

log-level=debug

 

#以下两项要特别注意:

#一定要与服务的脚本文件里参数一致,否则服务启动会报错

#开启debug模式的cetus生成的日志文件量还是挺可观的,如果必须,一定要配置到容量大,速度快的磁盘上面

pid-file =cetus6001.pid

log-file=/lhdata/cetus/cetus_6001.log

 

 

#从库延迟及下线阈值时间设置

disable-threads=false

check-slave-delay=true

slave-delay-down=60

slave-delay-recover=1

 

# Proxy进程意外终止,会自动启动一个新进程

keepalive=true

verbose-shutdown=true

log-backtrace-on-crash=true

 

特别要注意的是cetus参数文件proxy.conf一定要设置成660才能启动,否则报错

chmod 660 proxy.conf

手动启动cetus

bin/cetus --defaults-file=conf/proxy.conf

cetus配置系统服务

#进入cetus源码文件夹

[root@mysql-node1scripts]# cd  cetus-master/scripts/

[root@mysql-node1scripts]# cp cetus.service  /etc/init.d/cetus

 

#修改关键参数,CETUS_HOME,CETUS_PID,CETUS_LOG一定要与实际配置成一致

[root@mysql-node1scripts]# vim /etc/init.d/cetus

#!/bin/bash

# chkconfig: - 30 21

# description: Cetus service.

# Source Function Library

./etc/init.d/functions

 

STARTTIMEOUT=12

STOPTIMEOUT=60

 

# Cetus Settings

CETUS_HOME=/usr/local/cetus

CETUS_CONF=${CETUS_HOME}/conf/proxy.conf

CETUS_SBIN=${CETUS_HOME}/bin/cetus

CETUS_PID=${CETUS_HOME}/cetus6001.pid

CETUS_LOG=/lhdata/cetus/cetus_6001.log

CETUS_EXEC=${CETUS_HOME}/libexec/cetus

CETUS_DAEMON="0"

...

 

#现在就可以通过服务的方式启动,关闭cetus

[root@mysql-node1scripts]# service cetusstatus

Usage:/etc/init.d/cetus {start|stop|restart}

cetus使用测试

启动关闭

#cetus启停
[root@mysql-node1 scripts]# service cetus stop Stopping cetus (via systemctl):                            [  OK  ] [root@mysql-node1 scripts]# service cetus start Starting cetus (via systemctl):                            [  OK  ]

#cetus端口确认,服务端口6001,管理端口7001
[root@mysql-node1 scripts]# netstat -lntp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address          Foreign Address        State       PID/Program name tcp        0      0 0.0.0.0:6001            0.0.0.0:*               LISTEN      21038/cetus tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      4452/sshd tcp        0      0 0.0.0.0:7001            0.0.0.0:*               LISTEN      21032/cetus tcp        2      0 127.0.0.1:32000         0.0.0.0:*               LISTEN      2671/java tcp6       0      0 :::3306                 :::*                    LISTEN      3314/mysqld

#可以看到,已经启动了9cetus,为什么会比配置的8个多1个呢?,因为多了1cetus守护进程
[root@mysql-node1 scripts]# ps -ef | grep cetu[s] root     21032     1  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21033 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21034 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21035 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21036 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21037 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21038 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21039 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf root     21040 21032  0 16:42 ?        00:00:00 /usr/local/cetus/libexec/cetus --defaults-file=/usr/local/cetus/conf/proxy.conf

简单SQL测试

打开后端数据库的general_log参数,查看最终在哪个实例上执行

--进入客户端mysql -h 192.168.113.201 -P 6001  -ucuser -pXXX


---以下都在读库执行
cuser@6001(none) 12:19:05>use cetus Database changed cuser@6001cetus 12:19:10>show tables; +-----------------+ | Tables_in_cetus | +-----------------+ | test            | +-----------------+ 1 row in set (0.01 sec) cuser@6001cetus 12:19:14>select * from test; #所有写操作都会在主库执行#这里发现写操作后第1select也会优先在主库上执行,后续都会在从库执行
cuser@6001cetus 12:19:33>insert into test values(4); Query OK, 1 row affected (0.01 sec) --insert后第一次select在主库
cuser@6001cetus 12:19:38>select * from test; --insert后第二次在从库执行
cuser@6001cetus 12:19:45>select * from test; #只要是显示指定了事务,事务必在主库执行
cuser@6001cetus 12:22:47>begin ; cuser@6001cetus 12:24:23>select * from test where id=1; cuser@6001cetus 12:24:31>select * from test2 where id=1; cuser@6001cetus 12:24:37>commit; #通过添加hints可以手动配置指定主库还是从库,需要在连接是加-c ##不过需要注意的是开启了显示事务后hints是无效的
mysql -h 192.168.113.201 -P 6001  -ucuser -papppw -c
select /*# mode=READWRITE */ id  from test;
select /*# mode=READ */ id  from test;

从库延迟测试

故意制造1个长更新,检查主从延迟超过60s后会发生什么

##cetus检测到从库超过阈值,自动将从库“逐出”
(pid=24449) 2018-12-08 08:35:05: (critical) Check slave delay no data:select p_ts from proxy_heart_beat.tb_heartbeat where p_id='/usr/local/cetus/conf_289583606_427107461'(pid=24449) 2018-12-08 08:35:05: (message) change backend: 10.231.34.196:3306 from type: readonly, state: down to type: readonly, state: down (pid=24449) 2018-12-08 08:35:05: (critical) Slave delay 70.647 seconds. Set slave to DOWN.

主从延迟降低后,检查cetus判断:

#可以看到cetus自动将从库加入到cetus群集中,此时从库又可以被使用了!
(pid=24662) 2018-12-08 08:54:30: (message) change backend: 10.231.34.196:3306 from type: readonly, state: online to type: readonly, state: online (pid=24661) 2018-12-08 08:54:30: (message) Slave delay 0.030 seconds. Recovered. Set slave to UP.

资源占用测试

通过使用sysbench对cetus进行长时间的只读,读写测试,发现对cpu和内存占用比想象中的要低很多。这样是不是也就意味着cetus可直接放到数据库服务器上运行了呢(穷的话)?
cpu占用图

网易cetus初探--读写分离


内存占用图


总结

cetus性能优越,读写分离基本上能满足绝大部分场景需求,下一篇将对cetus基准压力测试做一个汇总,cetus很棒

以上是关于网易cetus初探--读写分离的主要内容,如果未能解决你的问题,请参考以下文章

网易cetus之读写分离

030:Cetus中间件和MHA读写分离

网易开源数据库中间件 Cetus 如何让 MySQL 更强大?

网易分片中间件cetus扩容方案

网易DBA女神驾到|带你快速玩转Cetus

网易开源中间件 -Cetus监控模块