最近在梳理某项目上各服务接口的性能情况,遇到两个问题。以下是定位和解决问题的一个思路,分享给大家。 业务之前并没有详细的性能日志记录,仅在电信机房(T机房)进行了性能测试,结果是各接口满足预期,服务上线。 在进一步对接口进行性能分析时,对各业务接口的关键路径添加了日志统计,通过日志进行分析,将接口的延迟进行统计,接入Grafana,观察数据后,发现两类问题。 连接MongoDB的服务,网通机房(C机房)延迟比电信机房(T机房)要高。 连接Mysql的服务,网通机房(C机房)延迟比电信机房(T机房)高。 NOTE: 这些服务接口,都是只读,没有写操作。 对两类问题分别进行排查: MongoDB 简单的排查后发现,MongoDB实例有过一次迁移,并且迁移后只保留了电信机房(T机房)的实例,网通机房(C机房)没有从库,所以网通机房(C机房)延迟比电信机房(T机房)高。对网通机房(C机房)部署了从库实例后,却意外发现电信机房(T机房)的延迟比网通机房(C机房)高了。再次排查后发现,代码中配置的MongoDB的读策略是secondary(从库优先),所以网通机房(C机房)有从库后,电信机房(T机房)也去网通机房(C机房)读取,导致了电信机房(T机房)的延迟变高。更改读策略为nearest(就近优先),有所好转,但并没有预想的效果那么好。仔细看下官方文档 The driver reads from a random member of the set that has a ping time that is less than 15ms slower than the member with the lowest ping time. Reads in the MongoClient::RP_NEAREST mode do not consider the member’s type and may read from both primaries and secondaries. 就会发现,nearest是在客户端维护一个到各个实例延迟小于15ms的集合,而我们电信机房(T机房)到网通机房(C机房)是光纤直连,延迟在12ms左右,所以,每次客户端可能会连接到电信机房(T机房),也可能到网通机房(C机房)。 这点在以后的应用中,大家可以注意下。 Mysql 在所有的服务中,只有一个服务接口是读mysql实现的,而这个接口的表现更是奇怪,网通机房(C机房)的延迟比电信机房(T机房)多100 ms+。
阅读全文

DB Proxy 原理[转]

在大型互联网站的数据库部署中,部署最多的数据库为MySQL。随着MySQL中Innodb存储引擎对事物的支持,MySQL在互联网公司部署中,应用量越来越多。典型应用MySQL的公司有Google、Taobao、Baidu等大型互联网公司。MySQL的优势在于其高扩展性和价格优势等。实际上,MySQL可以免费应用于企业级的部署中。

在MySQL复制方式部署中,有两种部署方式:同步复制和异步复制。同步复制采用NDB存储引擎,异步复制需要使用mysql-proxy结合master-slave实现。

mysql-proxy是一个MySQL的代理服务器,用户的请求先发向mysql-proxy,然后mysql-proxy对用户的数据包进行分析,从下一层的mysql 数据库中选择一台数据库,将用户的请求包交给mysql处理。

首先MySQL Proxy 以服务器的身份接受客户端的请求,根据相应配置对这些请求进行分析处理,然后以客户端的身份转发给相应的后端数据库服务器,再接受服务器的信息,然后返回给客户端。所以MySQL Proxy需要同时实现客户端和服务器的协议。由于要对客户端发送过来的SQL语句进行分析,还需要包含一个SQL解析器。MySQL Proxy通过使用lua脚本,来实现复杂的连接控制和过滤,从而实现读写分离和负载平衡。所以部署MySQL-Proxy需要安装运行Lua语言的环境。典型的MySQL-Proxy应用为实现读写分离。

异步复制主要为了解决读写分离的问题。因为用户对网站的访问有读操作多,写操作少的特点。甚至像taobao.com这样的网站读写比例高达10:1,所以采用MySQL-Proxy结合主从异步复制实现读写分离是非常重要的增快访问速度的方法。这样如果有更高的用户访问需求,通过增加slave机器,不会对现有系统提供的服务产生影响而实现很好的、很灵活的业务扩展。


阅读全文

需要保存一些创建表的语句,这些语句的表前缀是可以设置的一个变量,就需要用到以下方法了,如果谁有更好的方法,请告知,谢谢。 mysql中使用变量执行sql语句: set @PREFIX = ‘fk_‘; create database fk_manage; use fk_manage; set @QUERY = concat(“create table “, @PREFIX, “user( id int(10) primary key auto_increment, name varchar(25) not null, password varchar(32) not null, email varchar(50), reg_date TIMESTAMP default 0, last_login TIMESTAMP default CURRENT_TIMESTAMP on update current_timestamp);“); prepare execsql from @QUERY; execute execsql; set @QUERY = concat(“create table “, @PREFIX, “role( id int(10) primary key auto_increment, name varchar(25) not null, action varchar(32) not null, inuse tinyint default 1 comment ‘1 for use,0 for stop’, create_date TIMESTAMP default CURRENT_TIMESTAMP);”
阅读全文

目前的工作是需要对用户的一些数据进行分析,每个用户都有若干条记录,每条记录中有用户的一个位置,是用经度和纬度表示的。

还有一个给定的数据库,存储的是一些已知地点以及他们的经纬度,内有43W多条的数据。

现在需要拿用户的经纬度和已知地点进行距离匹配,如果它们之间的距离小于一定的数据,比如说500米,就认为用户是在这个地点。

MYSQL本身是支持空间索引的,但是在5.x的版本中,取消了对Distance()和Related()的支持,参考这里:MySQL 5.1参考手册 :: 19. 中的空间扩展 19.5.6. 测试几何类之间空间关系的函数,无法使用空间的距离函数去直接去查询距离在一定范围内的点。所以,我首先想到的是,对每条记录,去进行遍历,跟数据库中的每一个点进行距离计算,当距离小于500米时,认为匹配。这样做确实能够得到结果,但是效率极其低下,因为每条记录都要去循环匹配40W条数据,其消耗的时间可想而知。经过记录,发现每条记录处理的时间消耗达到1700ms,针对每天上亿的数据量,这样一个处理速度,让人情何以堪啊。。。

我自己也有个想法,就是找到每条记录所在点的经纬度周围的一个大概范围,比方说正方形的四个点,然后使用mysql的空间计算,使用MBR去得出点在这个矩形内的已知记录,然后进行匹配。可惜,自己没想出能计算到四个点经纬度的方法。

意外的,查询到了一个关于这个计算附近地点搜索初探,里面使用python实现了这个想法。

所以参考了一下原文中的算法,使用PHP进行了实现。

实现原理也是很相似的,先算出该点周围的矩形的四个点,然后使用经纬度去直接匹配数据库中的记录。

红色部分为要求的搜索范围,绿色部分我们能间接得到的结果范围

红色部分为要求的搜索范围,绿色部分我们能间接得到的结果范围


阅读全文

如何使用mysql 命令行 查看mysql数据库大小、表大小、数据大小、索引大小:

select * from information_schema.TABLES 
  where information_schema.TABLES.TABLE_SCHEMA='databasename'
  and information_schema.TABLES.TABLE_NAME='tablename'G

返回结果:

*************************** 1. row ***************************
  TABLE_CATALOG: def
   TABLE_SCHEMA: databasename
     TABLE_NAME: tablename
     TABLE_TYPE: BASE TABLE
         ENGINE: MyISAM
        VERSION: 10
     ROW_FORMAT: Dynamic
     TABLE_ROWS: 6422930
 AVG_ROW_LENGTH: 213
    DATA_LENGTH: 1370884700
MAX_DATA_LENGTH: 281474976710655
   INDEX_LENGTH: 412930048
      DATA_FREE: 0
 AUTO_INCREMENT: 6422931
    CREATE_TIME: 2012-05-11 05:00:02
    UPDATE_TIME: 2012-05-22 15:12:06
     CHECK_TIME: 2012-05-11 09:58:52
TABLE_COLLATION: utf8_general_ci
       CHECKSUM: NULL
 CREATE_OPTIONS: 
  TABLE_COMMENT: 'table comment'
1 row in set (0.00 sec)

其中:

information_schema.TABLES.TABLE_SCHEMA = ‘databasename’ and information_schema.TABLES.TABLE_NAME = ‘tablename’

信息存储在information_schema.TABLES这个表中,TABLE_SCHEMA 对应数据库名,TABLE_NAME 对应表名。

# TABLE_ROWS 代表拥有的数据行数。

# 总大小 = DATA_LENGTH(数据大小) + INDEX_LENGTH(索引大小)

结果以字节为单位,除1024为K,除1048576(=1024*1024)为M。


阅读全文

在本机搭建测试环境时,使用了mysqldump导出了一个数据库文件,将近500M,即使是压缩后也有100M左右,在通过mysqldump导入时,发生了错误: “MySQL server has gone away.”。

个人猜测,发生 MySQL server has gone away 问题的原因很可能就是数据文件过大,导致超时。

所以对mysql进行修改:修改my.ini(在lnix/unix下是my.cnf)文件,加大超时参数

wait_timeout=2888888

如果没有此参数,直接在my.ini/my.cnf文件末尾一行添加上即可。

重启mysql。

最后再次执行导入语句

mysql -uroot -p123456 test_data < D:Xampsqldatatest.sql

注:在使用mysqldump时要注意,客户端mysqldump工具的版本要高于等于服务器的版本。


阅读全文

MySQL怎样优化WHERE子句

此次讨论的为处理WHERE子句而进行的优化。例子中使用了 SELECT 语句,同样也适用于DELETE和UPDATE语句中的WHERE子句。

下面列出了MySQL执行的部分优化:

去除不必要的括号:

((a AND b) AND c OR (((a AND b) AND (c AND d))))

-> (a AND b AND c) OR (a AND b AND c AND d)

常量重叠:

(a<b AND b=c) AND a=5

-> b>5 AND b=c AND a=5

去除常量条件(由于常量重叠需要):

(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6)

-> B=5 OR B=6

索引使用的常数表达式仅计算一次。


阅读全文

作者的图片

DigDeeply

Technology Stack: PHP/Openresty/GoLang, and so on…

Web Develop Eneigneer

Beijing China