欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

memcached_functions在mysql5.1中的测试

程序员文章站 2022-05-07 15:08:32
测试目的: 1. 在mysql5.1的触发器中使用 UDFs 直接更新 Memcached 的内容,减轻了应用程序设计和编写的复杂性。 2. 熟悉它的应用场景,考虑是否能在合适...

测试目的:

1. 在mysql5.1的触发器中使用 UDFs 直接更新 Memcached 的内容,减轻了应用程序设计和编写的复杂性。

2. 熟悉它的应用场景,考虑是否能在合适的场景里面使用这样的部署。

一. 测试软硬件环境:

1. 硬件环境:

测试程序:192.168.1.71机器(HP DL360 G4p 2G内存,单颗双核Xeon(TM) CPU 3.00)

mysql机器:192.168.1.61 端口:3306 (DELL 2850 8G内存,两颗双核Xeon(TM) CPU 3.00)

memcached机器: 192.168.3.184 端口:11900 (启动参数:memcached -p 11900 -c 8000 -m 128 -d -r -u root)

2. 软件环境:

(1). 安装memcached-1.2.6, libevent-1.4.4-stable,libmemcached-0.30(不在这里说明)

(2). 安装mysql5.1(不在这里说明)

(3). 安装memcached_functions_mysql

wget https://download.tangent.org/memcached_functions_mysql-0.9.tar.gz

tar zxvf memcached_functions_mysql-0.9.tar.gz

./configure --with-mysql=/usr/local/mysql51/bin/mysql_config

make && make install

在mysql的shell中执行memcached_functions_mysql源码目录下的sql/install_functions.sql

或者运行memcached_functions_mysql源码目录下utils/install.pl这个perl脚本,把memcache function作为UDF加入mysql。

(4).检查安装是否成功

mysql> select name,dl from mysql.func;

+------------------------------+---------------------------------+

| name | dl |

+------------------------------+---------------------------------+

| memc_add | libmemcached_functions_mysql.so |

| memc_add_by_key | libmemcached_functions_mysql.so |

| memc_servers_set | libmemcached_functions_mysql.so |

| memc_server_count | libmemcached_functions_mysql.so |

| memc_set | libmemcached_functions_mysql.so |

| memc_set_by_key | libmemcached_functions_mysql.so |

| memc_cas | libmemcached_functions_mysql.so |

| memc_cas_by_key | libmemcached_functions_mysql.so |

| memc_get | libmemcached_functions_mysql.so |

| memc_get_by_key | libmemcached_functions_mysql.so |

| memc_delete | libmemcached_functions_mysql.so |

| memc_delete_by_key | libmemcached_functions_mysql.so |

| memc_append | libmemcached_functions_mysql.so |

| memc_append_by_key | libmemcached_functions_mysql.so |

| memc_prepend | libmemcached_functions_mysql.so |

| memc_prepend_by_key | libmemcached_functions_mysql.so |

| memc_increment | libmemcached_functions_mysql.so |

| memc_decrement | libmemcached_functions_mysql.so |

| memc_replace | libmemcached_functions_mysql.so |

| memc_replace_by_key | libmemcached_functions_mysql.so |

| memc_servers_behavior_set | libmemcached_functions_mysql.so |

| memc_servers_behavior_get | libmemcached_functions_mysql.so |

| memc_behavior_set | libmemcached_functions_mysql.so |

| memc_behavior_get | libmemcached_functions_mysql.so |

| memc_list_behaviors | libmemcached_functions_mysql.so |

| memc_list_hash_types | libmemcached_functions_mysql.so |

| memc_list_distribution_types | libmemcached_functions_mysql.so |

| memc_udf_version | libmemcached_functions_mysql.so |

| memc_libmemcached_version | libmemcached_functions_mysql.so |

| memc_stats | libmemcached_functions_mysql.so |

| memc_stat_get_keys | libmemcached_functions_mysql.so |

| memc_stat_get_value | libmemcached_functions_mysql.so |

+------------------------------+---------------------------------+

32 rows in set (0.00 sec)

二. 测试用例设计情况:

(1).新建两张表:urls和results,用来更新urls表里面的内容,让系统自动更新memcached的内容。results用来记录更新memcached失败的记录。

sql语句如下:

use tests;

drop table if exists urls;

CREATE TABLE `urls` (

`id` int(10) NOT NULL,

`url` varchar(255) NOT NULL DEFAULT '',

PRIMARY KEY (`id`)

);

drop table if exists results;

CREATE TABLE `results` (

`id` int(10) NOT NULL,

`result` varchar(255) NOT NULL DEFAULT 'error',

`time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY (`id`)

);

(2). 建立三个trigger.

当向urls表里面插入数据时,对memcached执行set操作,trigger如下:

DELIMITER //

DROP TRIGGER IF EXISTS url_mem_insert;

CREATE TRIGGER url_mem_insert

BEFORE INSERT ON urls

FOR EACH ROW BEGIN

set @mm = memc_set(NEW.id, NEW.url);

if @mm <> 0 then

insert into results(id) values(NEW.id);

end if;

END //

DELIMITER ;

当对urls表里面的数据进行更新时,对memcached执行replace操作,trigger如下:

DELIMITER //

DROP TRIGGER IF EXISTS url_mem_update;

CREATE TRIGGER url_mem_update

BEFORE UPDATE ON urls

FOR EACH ROW BEGIN

set @mm = memc_replace(OLD.id,NEW.url);

if @mm <> 0 then

insert into results(id) values(OLD.id);

end if;

END //

DELIMITER ;

当对urls表里面的数据进行删除操作时,对memcached执行delete操作,trigger如下:

DELIMITER //

DROP TRIGGER IF EXISTS url_mem_delete;

CREATE TRIGGER url_mem_delete

BEFORE DELETE ON urls

FOR EACH ROW BEGIN

set @mm = memc_delete(OLD.ID);

if @mm <> 0 then

insert into results(id) values(OLD.id);

end if;

END //

DELIMITER ;

(3). 设置memcached相关参数

设置同时UDF操作的memcaced的机器IP和端口:

mysql> SELECT memc_servers_set('192.168.3.184:11900');

+---------------------------------------+

| memc_servers_set('192.168.3.184:11900') |

+---------------------------------------+

| 0 |

+---------------------------------------+

1 row in set (0.00 sec)

mysql> select memc_server_count();

+---------------------+

| memc_server_count() |

+---------------------+

| 1 |

+---------------------+

1 row in set (0.00 sec)

在mysql命令行列出可以修改memcached参数的行为:

mysql> select memc_list_behaviors()\G

*************************** 1. row ***************************

memc_list_behaviors():

MEMCACHED SERVER BEHAVIORS

MEMCACHED_BEHAVIOR_SUPPORT_CAS

MEMCACHED_BEHAVIOR_NO_BLOCK

MEMCACHED_BEHAVIOR_TCP_NODELAY

MEMCACHED_BEHAVIOR_HASH

MEMCACHED_BEHAVIOR_CACHE_LOOKUPS

MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE

MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE

MEMCACHED_BEHAVIOR_BUFFER_REQUESTS

MEMCACHED_BEHAVIOR_KETAMA

MEMCACHED_BEHAVIOR_POLL_TIMEOUT

MEMCACHED_BEHAVIOR_RETRY_TIMEOUT

MEMCACHED_BEHAVIOR_DISTRIBUTION

MEMCACHED_BEHAVIOR_BUFFER_REQUESTS

MEMCACHED_BEHAVIOR_USER_DATA

MEMCACHED_BEHAVIOR_SORT_HOSTS

MEMCACHED_BEHAVIOR_VERIFY_KEY

MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT

MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED

MEMCACHED_BEHAVIOR_KETAMA_HASH

MEMCACHED_BEHAVIOR_BINARY_PROTOCOL

MEMCACHED_BEHAVIOR_SND_TIMEOUT

MEMCACHED_BEHAVIOR_RCV_TIMEOUT

MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT

MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK

MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK

1 row in set (0.00 sec)

设置MEMCACHED_BEHAVIOR_NO_BLOCK为打开状态,这样在memcached出现问题时(不能连接时)

数据继续插入到mysql中,报错提示,如果不设置此值,如果memcached失败,mysql需要等到timeout

才可以插入到表中。

mysql> select memc_servers_behavior_set('MEMCACHED_BEHAVIOR_NO_BLOCK','1');

+--------------------------------------------------------------+

| memc_servers_behavior_set('MEMCACHED_BEHAVIOR_NO_BLOCK','1') |

+--------------------------------------------------------------+

| 0 |

+--------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> select memc_servers_behavior_set('MEMCACHED_BEHAVIOR_TCP_NODELAY','1');

+-----------------------------------------------------------------+

| memc_servers_behavior_set('MEMCACHED_BEHAVIOR_TCP_NODELAY','1') |

+-----------------------------------------------------------------+

| 0 |

+-----------------------------------------------------------------+

1 row in set (0.00 sec)

三. 简单的功能测试:

1. 向表urls里面插入数据,然后查memcached是否也set进数据:

mysql> insert into urls (id,url) values (1, 'https://www.sina.com.cn');

Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select memc_get('1');

+------------------------+

| memc_get('1') |

+------------------------+

| https://www.sina.com.cn |

+------------------------+

1 row in set (0.00 sec)

1> telnet 192.168.3.184 11900

Trying 192.168.3.184...

Connected to 192.168.3.184 (192.168.3.184).

Escape character is '^]'.

get 1

VALUE 1 0 22

https://www.sina.com.cn

END

2.更新表urls里面的数据,然后查询memcached里面是否也更新:

mysql> update test.urls set url='https://blog.sina.com.cn' where id=1;

Query OK, 1 row affected, 1 warning (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql> select memc_replace('1','https://blog.sina.com.cn');

+---------------------------------------------+

| memc_replace('1','https://blog.sina.com.cn') |

+---------------------------------------------+

| 0 |

+---------------------------------------------+

1 row in set (0.00 sec)

mysql> select memc_get('1');

+-------------------------+

| memc_get('1') |

+-------------------------+

| https://blog.sina.com.cn |

+-------------------------+

1 row in set (0.00 sec)

1> telnet 192.168.3.184 11900

Trying 192.168.3.184...

Connected to 192.168.3.184 (192.168.3.184).

Escape character is '^]'.

get 1

VALUE 1 0 23

https://blog.sina.com.cn

END

3.删除表urls里面的数据,然后查memcached是否也删除:

mysql> delete from test.urls where id=1;

Query OK, 1 row affected, 1 warning (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

mysql> select memc_get('1');

+---------------+

| memc_get('1') |

+---------------+

| NULL |

+---------------+

1 row in set (0.00 sec)

1> telnet 192.168.3.184 11900

Trying 192.168.3.184...

Connected to 192.168.3.184 (192.168.3.184).

Escape character is '^]'.

get 1

END

四. 利用php脚本insert, update,delete表urls里面的数据,进行测试。

每条记录的平均长度是:17K

单独向表urls里面插入10万条记录需要的时间为:75秒

单独对表urls里面更新10万条记录需要的时间为:70秒

单独对表urls里面删除10万条记录需要的时间为:105秒

同时进行30万数据的insert,update, delete操作需要时间为:241秒

上面操作都没有memcached失败情况:

mysql> select * from results;

Empty set (0.00 sec)

测试脚本如下:

插入脚本:

0> more a.php

$conn = mysql_connect("192.168.1.61","test","test") or die(mysql_error());

mysql_select_db("test",$conn) or die(mysql_error());

//$sql = "show tables";

echo date("Y-m-d H:i:s");

//mysql_query($sql) or die(mysql_error());

for ($i=1; $i<=100000; $i++) {

$sql="insert into urls (id,url) values ($i, 'https://$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i.com');";

mysql_query($sql) or die(mysql_error());

}

echo "\n";

echo date("Y-m-d H:i:s");

?>

更新脚本:

0> more b.php

$conn = mysql_connect("192.168.1.61","test","test") or die(mysql_error());

mysql_select_db("test",$conn) or die(mysql_error());

//$sql = "show tables";

echo date("Y-m-d H:i:s");

//mysql_query($sql) or die(mysql_error());

for ($i=1; $i<=100000; $i++) {

$sql="update test.urls set url='https://xxxx.$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i$i.com' where id=$i;";

mysql_query($sql) or die(mysql_error());

}

echo "\n";

echo date("Y-m-d H:i:s");

?>

删除脚本:

0> more c.php

$conn = mysql_connect("192.168.1.61","test","test") or die(mysql_error());

mysql_select_db("test",$conn) or die(mysql_error());

//$sql = "show tables";

echo date("Y-m-d H:i:s");

//mysql_query($sql) or die(mysql_error());

for ($i=1; $i<=100000; $i++) {

$sql="delete from test.urls where id=$i;";

mysql_query($sql) or die(mysql_error());

}

echo "\n";

echo date("Y-m-d H:i:s");

?>

五. 结论:

测试依赖的环境比较多,可能数据会不准确。整体来看速度还不错。

适合项目应用相对比较小的场合。

优点:

触发器中使用 UDFs 直接更新 Memcached 的内容,减轻了应用程序设计和编写的复杂性。

缺点:

1. 如果出现mysql服务重启,需要重新设置连接memcached关系(SELECT memc_servers_set('192.168.3.184:11900'))

2. 有可能存在bug问题,导致mysql的crash(测试时没遇到:)).

真正的线上环境比这个复杂很多。我想到的需要考虑的问题:

1. 网络因素,mysql和memcached是否放在同一IDC,他们之间的网络性能是否很好。网络性能越好,速度肯定越快,如果使用本机的memcached能适当的减少网络开销。

2. 插入的数据量,向mysql插入每条记录的size,以及向memcached里面更新的数据size大小。更新mysql,memcached的数据size越大,更新的速度越慢。

所以前期规划好,在memcached里面存那两列(key-value)是关键。

3. 延时问题需要考虑,mysql所在机器如果资源使用比较狠,会导致更新memcached慢(出现类似m/s的延时问题)。

4. 考虑容灾问题,如果两者中有down出现时,需要考虑怎么恢复,当前的测试是这样考虑的:建一张错误表,如果在出现更新mc出现问题时,自动把更新错误的记录插到

一张表里面,通过查这张表,可以知道哪些数据在什么时间更新错误,如果应用于生产环境,需要考虑监控和出现问题时恢复工作(写好脚本完善这个工作)。

5. mysql自身因素,例如执行的mysql语句效率,以及连接mysql的client程序(php)的连接开销等等。