(1)MySQL-Proxy负载平衡测试中遇到的问题及其分析
(a)在0.8.1版mysql-proxy的负载平衡测试中,出现了如下的测试结果:
第一次启动mysql-proxy: * 有三台backend服务器,104,110和111
(0次) (50580次) (49374次) |
(b)分析上述测试结果可以得出这样的结论:
①在第一次启动mysql-proxy后,10万次查询中有一部分(8.5%)流向了主服务器(104),剩下的查询在从服务器110和111中也没有实现均衡分配, 由此可知,在本次测试中,mysql-proxy的负载平衡没有实现并且主服务器还承担一部分查询操作;
②第一次启动mysql-proxy后,先执行了一次10万次查询,然后继续执行同样的测试时,不但所有的查询都集中在从服务器(110和111), 而且从服务器之间也基本实现了查询次数的均衡分配;
那么为什么会出现上面奇怪的结论呢?
想知道结果的话,就要深入分析mysql-proxy的工作机制。
#想了解mysql-proxy的工作机制的话请参照【(2)MySQL-Proxy工作流程】。
(c)了解完mysql-proxy的工作机制,继续分析出现结论(b)的原因:
①当mysql-proxy处于第一次启动后,连接池中没有创建任何数据库服务器的连接。
当第一次查询请求过来后,根据balance.lua中的idle_ro()逻辑,mysql-proxy选择从连接池中拿从服务器的连接。
然而此时的连接池中没有任何连接,那么根据rw-splitting.lua中的connect_server()逻辑,
mysql-proxy没有拿到任何连接时,优先从连接池中拿主服务器的连接,此时mysql-proxy就会默认创建一个主服务器的连接;
②查询请求越来越多,mysql-proxy会不断的创建主服务器的连接。当主服务器的连接数超过最低空闲连接数(min_idle_connections)后,
mysql-proxy才会继续创建第一个从数据库的连接;
③mysql-proxy依次按照上述规则创建数据库连接,直至所有的数据库连接都被创建过并且其数目达到最低空闲连接数(min_idle_connections);
④当所有的主从数据库连接都被创建过后,再有查询请求过来的话,mysql-proxy会按照从服务器选择函数idle_ro()的逻辑来选择当前连接状态最少的从服务器进行连接(即实现了负载均衡)。
⑤有了上面四步的解析,现在应该对出现结论(b)的原因很清楚了吧。
(d)附录→关于在mysql-proxy0.8.0和0.8.1中实现负载均衡的脚本修正:
* 修改文件: /usr/local/mysql_proxy_0.8.1/lib/mysql-proxy/lua/proxy/balance.lua *修改函数:idle_ro() * < 表删除; > 表追加; < local max_conns_ndx = 0 --- > local max_conns_ndx = math.random(2,#proxy.global.backends) > local s_tmp = proxy.global.backends[max_conns_ndx] > local conns_tmp = s_tmp.pool.users[proxy.connection.client.username] > if s_tmp.type == proxy.BACKEND_TYPE_RO and > s_tmp.state ~= proxy.BACKEND_STATE_DOWN and > conns_tmp.cur_idle_connections > 0 then > max_conns = s_tmp.connected_clients > else > max_conns_ndx = 0 > end
(2)MySQL-Proxy工作流程(如图附件proxy_main.jpg所示):
#连接池连接规则的创建在rw-splitting.lua中完成。
第一步:
按照backend服务器设置的顺序(通常是主服务器+从服务器若干台),当client发起连接时,
就先在没有满足最低空闲连接数的服务器上创建一个连接。
第二步:
当此次查询是读操作时,根据balance.lua中的idle_ro()逻辑选择从连接池中拿从服务器的连接。
从服务器选择函数idle_ro()的逻辑是选择当前为连接状态最少的服务器进行连接的(前提是当前连接池中有从服务器的连接)
第三步:
最后还没有拿到连接时,从连接池中拿主服务器的连接。