memcached&redis性能测试

  categories:资料  tags:  author:

一、Memcached

1.1、memcached简介

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。但是它并不提供冗余(例如,复制其hashmap条目);当某个服务器S停止运行或崩溃了,所有存放在S上的键/值对都将丢失。

Memcached由Danga Interactive开发,其最新版本发布于2010年,作者为Anatoly Vorobey和Brad Fitzpatrick。用于提升LiveJournal . com访问速度的。LJ每秒动态页面访问量几千次,用户700万。Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。

1.2、Memcached是如何工作的

Memcached的神奇来自两阶段哈希(two-stage hash)。Memcached就像一个巨大的、存储了很多<key,value>对的哈希表。通过key,可以存储或查询任意的数据。客户端可以把数据存储在多台memcached上。当查询数据时,客户端首先参考节点列表计算出key的哈希值(阶段一哈希),进而选中一个节点;客户端将请求发送给选中的节点,然后memcached节点通过一个内部的哈希算法(阶段二哈希),查找真正的数据(item)。举个列子,假设有3个客户端1, 2, 3,3台memcached A, B, C:Client 1想把数据”tuletech”以key “foo”存储。Client 1首先参考节点列表(A, B, C),计算key “foo”的哈希值,假设memcached B被选中。接着,Client 1直接connect到memcached B,通过key “foo”把数据”tuletech”存储进去。Client 2使用与Client 1相同的客户端库(意味着阶段一的哈希算法相同),也拥有同样的memcached列表(A, B, C)。于是,经过相同的哈希计算(阶段一),Client 2计算出key “foo”在memcached B上,然后它直接请求memcached B,得到数据”tuletech”。

1.3、memcached提供的操作

Memcached的客户端api接口提供了如下的方法存储和获取缓存数据,并且这节方法在不同的客户端都是一致的:

get(key):读取数据从缓存中,如果数据存在的话返回值,否则返回Null,nil,underfined。

Set(key,value [,expiry]):写入缓存数据value,如果key已经存在了就更新value值,否则就增加一个新的key/value对,如果设定了expiry值,超过设定expiry时间后键值对就失效,时间单位是秒。

Add(key,value, [,expiry]):添加键值对到缓存如果key不存在的话。

Replace(key ,value [,expiry]:替换已经存在的键值对。

Deleted(key [, time]):从缓存中删除键,如果提供一个时间,在这段时间内这个键是处于阻塞状态。

二、安装部署Memcached服务

2.1、安装libevent库

memcached使用libevent库实现网络连接服务,理论上可以处理无限多的连接,但是它和Apache不同,它更多的时候是面向稳定的持续连接的,所以它实际的并发能力是有限制的。在保守情况下memcached的最大同时连接数为200,这和Linux线程能力有关系,这个数值是可以调整的。 关于libevent可以参考相关文档。memcachd有自己的内存分配算法和管理方式,它和共享内存没有关系,也没有共享内存的限制,通常情况下,每个memcached进程可以管理2GB的内存空间,如果需要更多的空间,可以增加进程数。

libevent下载地址:http://down1.chinaunix.net/distfiles/libevent-2.0.16-stable.tar.gz

# wget  http://down1.chinaunix.net/distfiles/libevent-2.0.16-stable.tar.gz

然后是正常步骤的解压安装:

# tar zxvf lilbevent-2.0.16-stable.tar.gz

# cd libevent-2.0.16-stable

# ./configure –prefix = /usr/local/libvent-2.0.16-stable

# make

#make install

测试libevent是否安装成功:

# ls –al /usr/local/libevent-2.0.16-stable/lib | grep libevent

修改配置文件把libevent库加入ld.so.conf文件

# nano /etc/ld.so.conf 加入/usr/local/libevent-2.0.16-stable/lib

运行 ldconfig否则运行memcached会报错,提示找不到so文件

2.2、安装memcached:

memcached下载地址:http://memcached.googlecode.com/files/memcached-1.4.13.tar.gz

# wget  http://memcached.googlecode.com/files/memcached-1.4.13.tar.gz

#tar memcached-1.4.13.tar.gz

# cd memcached-1.4.13

# ./configure

# make &make install

测试是否成功安装memcached:

wps_clip_image-30927[2][1]

2.3、编译安装magent代理:

magent是一款开源的memcached代理服务器软件,magent是解决memcached的单点故障的解决方案;magent的hash算法:magent采用的是:Consistent Hashing原理,Consistent Hashing如下所示:首先求出memcached服务器(节点)的哈希值, 并将其配置到0~232的圆(continuum)上。 然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。 然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。 如果超过232仍然找不到服务器,就会保存到第一台memcached服务器上。

wps_clip_image-13050[2][1]
编译安装magent:

# wget http://memagent.googlecode.com/files/magent-0.5.tar.gz

# mkdir magent

# cd magent/

# tar zxvf magent-0.5.tar.gz

# cd magent/

# nano magent.c 加入如下宏定义:

(# ifndef SSIZE_MAX

# define SSIZE__MAX 32767

# endif)否则编译会报错:未指定最大值

magent.c:729: error: ‘SSIZE_MAX’ undeclared (first use in this function)

#/sbin/ldconfig

# sed -i “s#LIBS = -levent#LIBS = -levent -lm#g” Makefile

# make

# cp magent  /usr/bin/magent

测试magent代理服务器是否安装成功:

root@ubuntu:~# magent

please provide -s “ip:port” argument

memcached agent v0.5 Build-Date: Feb 21 2012 16:39:44

Usage:

-h this message

-u uid

-g gid

-p port, default is 11211. (0 to disable tcp support)

-s ip:port, set memcached server ip and port

-b ip:port, set backup memcached server ip and port

-l ip, local bind ip address, default is 0.0.0.0

-n number, set max connections, default is 4096

-D don’t go to background

-k use ketama key allocation algorithm

-f file, unix socket path to listen on. default is off

-i number, set max keep alive connections for one memcached server, default is 20

-v verbose

三、memcached集群测试

3.1、测试环境

1.Memcached提供了很多客户端api,可供java,c,c++,python…的客户端的调用,在这里我们用python这门语法优雅功能强大的语言进行此次测试。

首先安装python lib库,运行如下命令:

# sudo  apt-get install python

自动安装完成后,默认版本为2.7.2。

测试是否正确安装:

wps_clip_image-17840[2][1]

接着安装python-memcached-latest.tar.gz.这是memcached的客户端api,安装好了之后直接用python操作调用memcached。

下载地址:ftp://ftp.tummy.com/pub/python-memcached/python-memcached-latest.tar.gz

安装如下:

# tar –zxvf python-memcached-latest.tar.gz

# cd python-memcached-latest

# python setup.py install

测试安装是否成功:

wps_clip_image-5339[2][1]

若 import memcache没有报错则导入无误。

2.memcached环境已经部署完毕,接下来分别在四台虚拟linux服务器上运行测试任务:

分别在四台台主机上启动配置相同的memcached服务:

wps_clip_image-28833[2][1]wps_clip_image-9197[2][1]

wps_clip_image-3807[2][1]wps_clip_image-30073[2][1]

在主机192.168.1.108上启动magent代理服务器:

wps_clip_image-27015[2][1]其中-s代表主服务器,-b 192.168.1.111:11211为备份服务器。

我为此写了一个python客户端程序(Memcached.py)调用magent代理往三个主服务器写入和读取数据。

3.2、测试脚本源码

”’

Created on 2012-2-22

@author: Administrator

”’

”’

multiprocess :

current instance

# Memcached –d –u root –m100 –l 192.168.1.108 –p 11211

# Memcached –d –u root –m100 –l 192.168.1.109 –p 11211

# Memcached –d –u root –m100 –l 192.168.1.110 –p 11211

# Memcached –d –u root –m100 –l 192.168.1.111 –p 11211

magent proxy

# magent  –u root –n 4096 –l 192.168.1.108 –p 11212 –s 192.168.1.108:11211

–s 192.168.1.109:11211 –s 192.168.1.101:11211 –b 192.168.1.111:11211

”’

if __name__ == ‘__main__':

import memcache

key = None

value = None

m = []

# 用代理节点实现数据写入和读取

magent = memcache.Client([‘192.168.1.108:11212′],debug = 1)

for i in range(8):    #测试向服务器写入8个数据

key = ‘key’+str(i)

value = ‘value’+str(i)

magent.set(key,value)

m.append(key)

server_one = memcache.Client([‘192.168.1.108:11211′],debug = 1

print(“server_one store list:”)

for keys in m:

values =server_one.get(keys)

print(values)

server_two = memcache.Client([‘192.168.1.109:11211′],debug = 1)

print(“server_two store list:”)

for keys in m:

values = server_two.get(keys)

print(values)

server_three = memcache.Client([‘192.168.1.110:11211′],debug = 1)

print(“server_three store list:”)

for keys in m:

values = server_three.get(keys)

print(values)

back_up_server = memcache.Client([‘192.168.1.111:11211′],debug = 1)

print(“back_up_server store list:”)

if back_up_server is not None:

print  “backup is not none”

for keys in m:

values = back_up_server.get(keys)

print(values)

运行程序:

# python Memcache.py

server_one store list:

None

value1

None

None

value4

None

None

value7

server_two store list:

value0

None

value2

None

None

value5

None

None

server_three store list:

None

None

None

value3

None

None

value6

None

back_up_server store list:

value0

value1

value2

value3

value4

value5

value6

value7

3.3、测试结论

测试结果和预期的一样,magent通过consistant hase算法根据key值的不同分别把value写入主服务器,如果备份服务器只有一个的话,把所以key_value映射到同一个备份服务器,相同的,我们可以启动几个备份服务器,这时候magent根据consistent hase 算法和写入主服务器一样的方式分别写入备份服务器。

当用命令杀死(kill)一个memcache主服务进程之后,如果通过magent代理节点取数据不会出现问题,结果和上面的一样。但是当我们把kill掉的memcache复活,再尝试取结果则出现故障,因为magent不会再从备份节点取数据,而是直接去复活的那个节点拿数据,而恢复的节点内无数据故出现读取None值的问题,这个问题有待解决。

二、Redis

2.1、Redis简介

Redis: REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。Redis提供了一些丰富的数据结构,包括lists, sets, ordered sets 以及hashes 还有和Memcached一样的strings结构.Redis当然还包括了对这些数据结构的丰富操作。redis是一个高性能的key-value数据库。redis的出现,很大程度补偿了memcached这类key-value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。redis提供了Python,Ruby,Erlang,PHP等客户端,使用很方便Redis的优点:

性能极高 Redis能支持超过 100K+每秒的读写频率。

丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。

原子性Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。

丰富的特性 Redis还支持 publish/subscribe, 通知, key 过期等等特性.

2.2、Redis常用的操作

Redis提供了string,set,list数据类型及操作:

strings数据类型及操作:

和memcached一样提供set,get操作。

Set key ‘value’

Get key

Set集合数据类型及操作:

SADD key member — 增加元素

SREM key member — 删除元素

SCARD key — 返回集合大小

SISMEMBER key member — 判断某个值是否在集合中

SINTER key1 key2 … keyN — 获取多个集合的交集元素

SMEMBERS key — 列出集合的所有元素

Redis的set是string类型的无序集合。set元素最大可以包含(2的32次方)个元素。

list数据类型及操作:

LPUSH key string — 将某个值加入到一个key列表头部

LPUSH key string — 将某个值加入到一个key列表末尾

LLEN key — 列表长度

LRANGE key start end — 返回列表中某个范围的值,相当于mysql里面的分页查询那样 LTRIM key start end — 只保留列表中某个范围的值

LINDEX key index — 获取列表中特定索引号的值,要注意是O(n)复杂度

LSET key index value — 设置列表中某个位置的值

LPOP key 抛出表头值

RPOP key — 和上面的LPOP一样,就是类似栈或队列的那种取头取尾指令,可以当成消息队列来使用了.

2.3、安装配置Redis

进入Redis管网: http://redis.io/download

# wegt  http://redis.googlecode.com/files/redis-2.4.4.tar.gz

# tar zxvf redis-2.4.2.tar.gz
# cd redis-2.4.2
# make
# make install
# cp redis.conf /etc/

第二步:修改配置

#vi /etc/redis.conf

我是按照下面这个博客上面的指导配置的:

http://blog.csdn.net/21aspnet/article/details/6960757

2.3.1、下载安装redis-python客户端

# sudo apt-get install python-redis 其实就是一个python文件(模块)。

检测是否安装成功成功:

wps_clip_image-31550[2][1]Import redis没有报错就说明成功安装。

启动并测试redis服务器:

wps_clip_image-3112[2][1]

启动成功,现在使用redis存储key-value.

wps_clip_image-6186[2][1]

存取成功.

2.3.2、配置redis分布式、主从同步

Redis和memcached一样实现了服务器的集群,在redis上是主从同步。

配置slave服务器如下:

我是在同一台主机上修改配置文件,当然多机环境也一样。

首先,复制redis.conf文件,命名为redis-slave.conf:

wps_clip_image-17681[2][1]

编辑:

# nano /etc/redis-slave.conf修改如下:

wps_clip_image-25608[2][1]

绑定从服务器端口:

wps_clip_image-3275[2][1]

绑定ip地址:127.0.0.1

设置从服务器的备份DB:

wps_clip_image-23935[2][1]

添加主服务器ip:port确认从服务器监听哪台主服务。

wps_clip_image-13979[2][1]

配置完成保存退出。

启动主从、服务器成功:

wps_clip_image-1293[2][1]

在python脚本中测试是否主从一致:

wps_clip_image-6673[2][1]

得到想要的值,配置redis的主从服务器成功。这里只是实现了简单的主从同步,redis的功能很全也很强大,分布式集群的实现需要深入学习后再实施。

三、Memcahced、Redis做mysql数据库缓存

3.1、安装mysql数据库

Ubuntu中安装mysql的方式很多,如在如源码编辑安装、deb包安装等。这次是我进行进行二进制版本安装的。

安装步骤:

#  http://downloads.mysql.com/archives.php   — 二进制mysql下载链接

#  mysql-5.1.54-ubuntu.tar.gz  –下载安装文件。

# tar –zxvf mysql-5.1.54-ubuntu.tar.gz –C /usr/local

# cd /usr/local

# mv myssql-5.1.54-ubuntu.tar.gz mysql  -将此目录命名为mysql

# cd mysql

# groupadd mysql

# useradd –g mysql mysql

# chown -R mysql .[注意小数点]—让该用户mysql对该目录用户使用权

chgrp -R mysql .

bin目录很重要,里面包含了mysql客户端和服务器,把它添加到环境变量中

nano /etc/profile –进入编辑状态

添加如下行

export PATH=$PATH:/usr/local/mysql/bin

完成后按住Ctrl+O进行保存,然后再按住Ctrl+x 退出

在scripts/下有个安装脚本,我们用它安装mysql

scripts/mysql_install_db –user=mysql –basedir=/usr/local/mysql –datadir=/usr/local/mysql/data

–第一个mysql:指是所属用户

–第二个mysql:指安装路径

–basedir:指安装路径

–datadir:指数据存放路径

让root拥有此目录的权限,当然除data外

chown -R root .  –目录所属root用户

chown -R mysql data –数据所属mysql用户

bin/mysqld_safe –user=mysql &  –启动mysql

3.设置开机自动启动。

每次敲mysqld_safe –user=mysql &很烦。接下来让它开机自动运行。

在support-files里有个mysql.server脚本,这就是启动脚本,只要把它放到系统启动自动运行目录里,就可以让mysql自动运行。

切换到系统启动脚本目录

cd /etc/init.d –自动启动目录

拷贝mysql.server并重命名为mysql

cp /usr/local/mysql/support-files/mysql.server mysql –拷贝文件并重命名

chmod +x /etc/init.d/mysql –让其具有运行权限

cd /etc/rc2.d

建立init.d/mysql的符号链接

ln -s /etc/init.d/mysql /etc/rc2.d/S20mysql

好了,全部完成,重启(reboot)。

3.2、安装MySQL-python库

要使用python连接mysql数据库需要一个MySQLdb,这个就好比java的jdbc,是一个用python写的api 库,下面是安装配置过程:

下载地址:http://ncu.dl.sourceforge.net/project/mysql-python/mysql-python/1.2.3/MySQL-python-1.2.3.tar.gz

# tar –zxvf MySQL-python-1.2.3.tar.gz

# cd MySQL-python-1.2.3

#在编译安装之前先把Python开发包安装好这个很重要!不然gcc报错,如下:

# sudo apt-get install python-dev

安装完成后继续执行如下命令:

MySQL-python-1.2.3# python setup.py build

MySQL-python-1.2.3# python setup.py install

安装完测试如下:

wps_clip_image-28908[2][1]

导入MySQLdb无误,说明安装成功了。

3.3、测试过程

3.3.1、redis vs memcached

首先测试在单线程下memcahced和redis缓存读写速度并分析数据得到结论,再测试在多线程下模拟并发时memcached/redis缓存读取数据的情况,所有的测试数据都由随机数函数控制产生,运行环境一样:

Configration:

Cpu:双核Intel® Atom™ CPU D525 @1.80GHz,内存2G,100M网卡OS:ubuntu11.10-server-x64

测试键/值长度为32 bytes

分别启动一个memcached、redis服务进程:

Memcached  –d –m268 –uzdxhave –l192.168.1.109 –p11211

Redis-server /etc/redis.conf

wps_clip_image-9691[2][1]

wps_clip_image-10492[2][1]

Redis配置图:

wps_clip_image-3713[2][1]

测试结果,源代码如下

在单线程情况下:

wps_clip_image-21289[2][1]

图3.3.1

wps_clip_image-8118[2][1]

图3.3.2

由上图3.3.2和3.3.2可以看出,在单线程条件下,相同的写入和读取数据次数 memcached的写入和读取时间都要优于redis缓存而且两者性能都比较稳定,没有出现连接服务器失败的情况。

接下来是在多线程情况下的测试,流程如下:在固定写入数量(2000)的条件下,开启多个线程同时连接(每个线程2000次写入/读取)memcached、redis服务器,统计结果如下:

wps_clip_image-15343[2][1]

图3.3.3

我在这次实验用的是多线程下模拟并发的环境,从图3.3.3实验数据和图表看来memcached表现很稳定,写入和读取时间相差不是很大,但是redis在低并发的时候表现比的比memcached好,当并发数超过10,就出现连接不稳定,连接不上服务器的情况,而memcached很适合那种高性能多并发的环境下。

结论:memcached是一个高性能多并发的缓存系统,适合简单的追求高性能,有独立服务器,和大内存的环境下,然而redis性能也不错,它提供更多的对内存数据的操作方式,可以自定义内存数据格式,适合有特殊需求,可备份内存数据,而它自身的支持分布式的更多功能还在开发之中。

3.3.2搭载memcached/redis缓存的mysql性能测试

测试流程:首先,在mysql数据库上新建一个数据库,数据库名test,在里面创建一个mytable表,表字段为num varcahr(50),val varchar(50):

wps_clip_image-11606[2][1]

接下来在单线程下分别对其读、写速度进行测试,写入数据结果图如下:

wps_clip_image-25561[2][1]

图3.3.4

从图3.2.4可以看出在没有搭载缓存服务器的情况下,mysql_set(草绿色)的写入性能是最好的,而且稳定行很高,因为当有新数据写入时是没有经过两次写操作(一次写入缓存),而是直接写入后台数据库,所以性能是最高的。

当把memcached/redis当做mysql的缓存服务器后,写入数据用时基本是单独不用缓存的两倍多一点,而且,redis(红色)做为缓存写入性能比memcached的要好。

接下来是各服务器读取数据的统计图表,如下图3.3.5:

wps_clip_image-18776[2][1]

图3.3.5

如上图3.3.5所示,在读取数据少于2000的时候,mysql_get,mem_mysql_get,redis_mysql_get的性能都差不多,随着读取数据量的增大,mysql_get性能直线下降,到了用户不能忍受的地步,而搭载了缓存的mysql,在读取数据少于10000的情况下读取性能非常稳定,而且速度比较理想。Memcached配合mysql和redis配合mysql在少于15000的读取数据量的情况下,性能差不多,但随着数据量的增大,redis-mysql相比memcached-mysql的性能下降的比较严重。

3.4、实验结论

在此次实验环境,在单线程条件下,单独测试memcached&redis服务器的性能,相同的写入和读取数据次数memcached的写入和读取性能都要优于redis缓存。在多线程模拟多并发的测试中memcached性能也较redis稳定。

然而,当memecached做为数据库缓存,读取数据速度是三者中最快的,而redis做为数据库缓存写入数据的性能略比memcached的高,搭载缓存服务器后测试mysql的写入速度下降严重,因为数据经过了两次写入操作,但是读取速度明显加快。在写入数据时客户端编码性能有待提高,在客户端实现的时候,这些应该是可以优化的。

3.5、测试源代码

#!/bin/env python/mysql-memcached

from threading import Thread

import sys

import memcache

class Workers(Thread):

def __init__(self, c, times, gs):

Thread.__init__(self)

self.c = c

self.times = times

self.gs = gs

self.completiontime = 0

self.name = c

def run(self):

import MySQLdb

from hashlib import md5

from time import time

startTime = time()

for i in range(self.times):

conn = MySQLdb.connect(host=’localhost’, user=’root’, passwd=’star’, db=’test’, port=3306)

mem = memcache.Client([‘192.168.1.109:11211′],debug=1)

cursor = conn.cursor()

hashval = md5(str(self.c) + str(i)).hexdigest()

if self.gs == ‘set':

if mem.get(hashval):

pass

else:

cursor.execute(‘insert into mytable values(“‘+hashval+'”,”‘+hashval+'”)’)

mem.set(hashval,hashval,60)

else:

row = mem.get(hashval)

if row:

#  print “get from memcached”

#  row = mem.get(hashval)

pass

else:

#  print “get from mysql”

cursor.execute(‘select * from mytable where num = “‘ + hashval + ‘”‘)

row = cursor.fetchone()

conn.commit()

cursor.close()

conn.close()

endTime = time()

self.completiontime = endTime – startTime

#chars = ‘1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20’.split(‘,’)

threads = []

for char in range(int(sys.argv[3])):

print char

gs = ‘get’

if sys.argv[1] == ‘set':

gs = ‘set’

timee = int(sys.argv[2])

t = Workers(char, timee, gs)

threads.append(t)

t.start()

for t in threads:

t.join()

print ‘Got ‘, t.name, t.gs, t.completiontime

#!/bin/env python/mysql

from threading import Thread

import sys

class Workers(Thread):

def __init__(self, c, times, gs):

Thread.__init__(self)

self.c = c

self.times = times

self.gs = gs

self.completiontime = 0

self.name = c

def run(self):

import MySQLdb

from hashlib import md5

from time import time

startTime = time()

for i in range(self.times):

conn = MySQLdb.connect(host=’localhost’, user=’root’, passwd=’star’, db=’test’, port=3306)

cursor = conn.cursor()

hashval = md5(str(self.c) + str(i)).hexdigest()

if self.gs == ‘set':

cursor.execute(‘insert into mytable values(“‘+hashval+'”,”‘+hashval+'”)’)

else:

cursor.execute(‘select * from mytable where num = “‘ + hashval + ‘”‘)

row = cursor.fetchone()

conn.commit()

cursor.close()

conn.close()

endTime = time()

self.completiontime = endTime – startTime

#chars = ‘1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20’.split(‘,’)

threads = []

for char in range(int(sys.argv[3])):

print char

gs = ‘get’

if sys.argv[1] == ‘set':

gs = ‘set’

times = int(sys.argv[2])

t = Workers(char, times, gs)

threads.append(t)

t.start()

for t in threads:

t.join()

print ‘Got ‘, t.name, t.gs, t.completiontime

#!/bin/env python/mysql-redis

from threading import Thread

import sys

import redis

class Workers(Thread):

def __init__(self, c, times, gs):

Thread.__init__(self)

self.c = c

self.times = times

self.gs = gs

self.completiontime = 0

self.name = c

def run(self):

import MySQLdb

from hashlib import md5

from time import time

startTime = time()

for i in range(self.times):

conn = MySQLdb.connect(host=’localhost’, user=’root’, passwd=’star’, db=’test’, port=3306)

red = redis.Redis(‘localhost’)

cursor = conn.cursor()

hashval = md5(str(self.c) + str(i)).hexdigest()

if self.gs == ‘set':

if red.get(hashval):

#           print “key-value in redis_memery”

pass

else:

cursor.execute(‘insert into mytable values(“‘+hashval+'”,”‘+hashval+'”)’)

red.set(hashval,hashval)

else:

row = red.get(hashval)

if row :

pass

#          print “get from redis”

# row = red.get(hashval)

else:

print “get from mysql”

cursor.execute(‘select * from mytable where num = “‘ + hashval + ‘”‘)

row = cursor.fetchone()

conn.commit()

cursor.close()

conn.close()

endTime = time()

self.completiontime = endTime – startTime

#chars = ‘1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20’.split(‘,’)

threads = []

for char in range(int(sys.argv[3])):

print char

gs = ‘get’

if sys.argv[1] == ‘set':

gs = ‘set’

times =int(sys.argv[2])

t = Workers(char, times, gs)

threads.append(t)

t.start()

for t in threads:

t.join()

print ‘Got ‘, t.name, t.gs, t.completiontime



快乐成长 每天进步一点点      京ICP备18032580号-1