基于lserver的mc 和 memcached的性能对比

April 24th, 2010
  • 测试环境描述

硬件:

虚拟机 VMware Workstation

内存 320M

Cpu 1.86G*2

软件

memcached-1.2.5

lserver 项目地址 http://code.google.com/p/lserver

基于lserver 的类似memcached服务器, test_mc.cpp, 实现代码如下

/*

*

*

* msn: ljw2001323500@163.com

* email: ljw2001323500@163.com

* author: 蓝金伟(lanjinwei)

* @2009

*

*/

#include “server.hpp”

#include “task.hpp”

#include “util.hpp”

#include <lbase/lbase.h>

lserver::server srv;

map<std::string, std::string> _kv;

void mcCallBack(lserver::datatask task)

{

lserver::connection* cnn = srv.getConnection();

std::string ip = cnn->clientIp(task._fd);

std::string data = task._data;

std::string cmd = “”;

std::string key = “”;

std::string value = “”;

data = data.substr(0, data.size()-2);

std::vector <std::string > result;

lbase::String::splitString(data,’ ‘,result);

std::string outstring = “”;

if (result.size() < 2)

{

outstring = “ERROR\r\n”;

lserver::write_back(task._fd, task._ver, outstring);

return;

}

cmd = result[0];

if (cmd == “get”)

{

key = result[1];

value = _kv[key];

//std::cout << “get” << ” ” << key  << ” = ” << value << std::endl;

char size[10]  = “”;

if (value == “”)

outstring = “END\r\n”;

else

{

outstring += “VALUE “;

outstring += key;

outstring += ” 0 “;

sprintf(size, “%d”, value.size());

outstring += size;

outstring += “\r\n”;

outstring += value;

outstring += “\r\n”;

outstring += “END\r\n”;

}

}

else if (cmd == “set”)

{

if (result.size() != 3)

outstring = “ERROR\r\n”;

else

{

key = result[1];

value = result[2];

//std::cout << key << ” = ” << value << std::endl;

_kv[key] = value;

outstring = “STORED\r\n”;

}

}

else

outstring = “ERROR\r\n”;

lserver::write_back(task._fd, task._ver, outstring);

return;

}

main()

{

std::string ename = “test_mcsrv”;

std::string pwd = “./”;

u_int32_t maxfd = 102400;

lserver::sys_init(ename, pwd, maxfd);

string ip = “127.0.0.1″;

srv.init(ip, 11211, 1000, 1024, 20, mcCallBack);

srv.run();

}

  • 测试结果

单连接,一个key重复set/重复100万次

Memcached Lserver+mc
每秒处理量 3800次/s 2700次/s
平均响应时间 0.26ms 0.37ms
Cpu占用 38% 55%
内存占用 2M 1M

单连接,一个key重复get/重复100万次

Memcached Lserver+mc
每秒处理量 3800次/s 2700次/s
平均响应时间 0.26ms 0.37ms
Cpu占用 30% 55%
内存占用 2M 1M

单连接,多个key值set/set100万次(个)

Memcached Lserver+mc
每秒处理量 3311次/s 2400次/s
平均响应时间 0.30ms 0.42ms
Cpu占用 40% 50%
内存占用 88M 77M

单连接,多个key值get/get100万次(个)

Memcached Lserver+mc
每秒处理量 3267次/s 2358次/s
平均响应时间 0.30ms 0.42ms
Cpu占用 40% 50%
内存占用 88M 77M
  • 结论

结果显示,Lserver的mc 比 memcached本身在综合素质上差20%-30%

opensqs0.0.1 应用代码示例

April 15th, 2010
#include “opensqs.hpp”
main(int argc, char **argv)
{
std::string queueName = “lanjinwei_test”;
if(argc > 1)
queueName = argv[1];
std::string domain = “127.0.0.1″;
opensqs::q q1(queueName, domain); //队列名称和domain
int rc = q1.createQueue(); //创建队列
//step 1. create queue
if(rc != opensqs::ERROK)
{
std::cerr << “Create Queue Fail!!” << rc << “[" << q1.err() << "]” << std::endl;
}
else
std::cerr << “Create Queue [ " << queueName << "]” << std::endl;
//step 2. push messages
for(int i=0;i<10;i++)
{
std::string messageid = “”;
std::string messagebody = lbase::String::toString(i);
rc = q1.push(messagebody); //push消息
if (rc != opensqs::ERROK)
{
std::cerr << “Push Fail!!” << rc << “[" << q1.err() << "]” << std::endl;
return 0;
}
else
std::cerr << “Push [" << messagebody << " ]” << std::endl;
}
while(1)
{
std::string messageid = “”;
std::string messagebody = “”;
rc = q1.pop(messageid, messagebody); //pop消息
if (rc != opensqs::ERROK)
{
std::cerr << “Pop Fail!!” << rc << “[" << q1.err() << "]” << std::endl;
return 0;
}
else if (messageid == “”)
break;
else
std::cerr << “Pop [" << messageid << " ] = [ "  <<  messagebody << "]” << std::endl;
}
//getchar();
}

目前支持 createQueue, deleteQueue, push, pop四个接口

Amzaon SQS 学习感受

March 22nd, 2010
  1. Amzaon SQS 特性:
Amazon SQS provides the following major features:
• Redundant infrastructure—Guarantees delivery of your messages at least once, highly concurrent
access to messages, and high availability for sending and retrieving messages
• Multiple writers and readers—Multiple parts of your system can send or receive messages at the
same time
SQS locks the message during processing, keeping other parts of your system from processing the
message simultaneously.
• Configurable settings per queue—All of your queues don’t have to be exactly alike
For example, one queue can be optimized for messages that require a longer processing time than
others.
• Variable message size—Your messages can be up to 8 KB in size
For even larger messages, you can store the contents of the message using the Amazon Simple
Storage Service (Amazon S3) or Amazon SimpleDB and use Amazon SQS to hold a pointer to the
Amazon S3 or Amazon SDB object. Alternately, you can split the larger message into smaller ones.
For more information about the services, go to the Amazon S3 detail page and the Amazon
SimpleDB detail page.
• Unlimited queues and messages—You can have as many queues and messages in the Amazon
SQS system as you want
• Access control—You can control who can send messages to a queue, and who can receive
messages from a queue

2.   分布式队列的几个特性

消息顺序: SQS由于分布式天然的特性无法保证消息自然有序, 需要应用层拼装   如果要求必须要有序 那么请提供消息排序字段,类似于序列号

至少一次的投递服务:  多个服务采用copy消息技术,可能会导致删除的时候 没有删除彻底 因此需要开发者应用层保证 可以连续处理两次消息

MEssage  sample :  这个没有看懂

3. 队列和消息的识别

队列识别: url  系统为每个队列和账户提供一个唯一的url 形式如下: http://queue.amazonaws.com/123456789012/queue2

消息识别: 消息发送方在SendMessage的时候 系统会分配一个id返回,但是发送方不能用这个去删除。  消息接收方 采用下面提到的收条去删除

收条(Receipt Handles):  接收方 收到消息后通过收条去读取或删除消息   比较特殊的是 对于同一个消息 多次接受后 收条是不同的

这个地方的设计比较难懂 但可以想到的是 接收方不能知道发出方的信息 比如消息id之类的 负责可能会有安全方面的问题吧

4.  消息的生命周期和消息的可见性

消息的可见性 这个是非常巧妙的一个设计(比我之前做的一个queue系统 先进多了) 但一个消息被接受者recived后 queue服务端会启动一个计时器,将该消息的可见性关闭 ,在关闭期内其他接受者不能再次获取该消息   如果计时器超时,则系统会再次打开该消息的可见性,该消息如果在关闭期未被删除 则可以再次被recived

由于可见性机制的存在 消息的生命周期就比较清晰:

消息被创建-》 消息被接受-》消息被删除

消息被接受期 别人不能再次接受, 在超时时间内如果未被删除  消息再次可见

另外 一个特别点就是 系统会自动删除4天前的消息

基础库lbase和lserver中发现的一点问题

March 21st, 2010

1.lbase里将socket封装好了,在lserver中的server::run()里又重复编写了一次。

2.lserver中,对libevent的初始化工作没有放在构造函数里或者init函数里。

3.在lbase里的tcp连接是基于select复用的,可以考虑直接将libevent集中在lbase库中。

具体实现中可以考虑这几种方案

(1)新建立tcp::request_lbe()来实现libevnt的tcp请求
(2)在tcp::request直接采用libevnt的机制重写,取代系统原始的select机制(推荐)
(3)在tcp::request多加入一个参数,决定是否采用libevent机制(不推荐,因为目前已经有7个参数了)

4.lbase下的code.cpp/code.hpp命名不符合习惯,改为encode.cpp/encode.hpp更佳。

吃货:)2-白菜花煮年糕

March 17th, 2010

从老家过年的早餐上传承的做法

  • 1.选嫩白菜花一把,的比较有滋味,掰做小条状
  • 2.选米做的年糕两根切片状,薄一点
  • 3.白菜花先下锅,炒至7分熟即可
  • 4.年糕片和(huo)水,倒入锅中,煮开一会儿
  • 5.见汤已开始有点稠即可收场,乘起
  • 6.主吃年糕,以鲜嫩白菜花辅之,
  • 7.最要紧是喝汤, 同时溶有年糕和白菜的精髓,
  • 8.喝完汤可随时添之,不必等碗中年糕吃完,乐趣即在于此

opensqs-进展报告

March 16th, 2010

opensqs0.0.1版本 , qmaster模块开发,测试完成(3分钟之前)(庆祝)!!
qmaster是opensqs的核心模块,节点和队列信息管理中心,是opensqs系统的智能中心

qmaster svn地址:

http://opensqs.googlecode.com/svn/trunk/src/qmaster

依赖

测试用例 http://opensqs.googlecode.com/svn/trunk/src/qmaster/qmaster_test

:) 下一步计划,qnode模块开发测试

得(de)看《无耻混蛋》

March 16th, 2010

得(de)看, 广西话讲起来就是 “得到看了” 的意思

也是偶然的巧合得(de)看,虽然有些场景血腥一点,我还是被吸引住看完,之后又意犹未尽

争锋相对又不露声色的 谈判,谈话和审讯,是精彩的地方,这种段落极多,有兴趣的看官可以关注
一直看到最后一场  刺杀希特勒的时候,才知道是虚构的,不知道是我笨还是导演太聪明

有点 《疯狂的石头》那种风格,只是玩笑开得更大

有个小酒馆血战的段子,据说是 三个杯子 引发的, 倒是没能明白,google了才知道,原来是 ”第三帝国“ 和 “三个杯子” 相冲了,外国人也有文字狱这么一说

三个杯子的解释

动态对象使用心得

March 16th, 2010

在编译opensqs基础库 lserver库中遇到了一些问题,将其记录备忘。

一、动态共享库简介

静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
创建共享库
g++ -g –c connection.cpp fd.cpp server.cpp task.cpp util.cpp

g++ -g –shared –o liblserver.so connection.o fd.o server.o task.o util.o

-shared是提示编译器创建动态共享库liblserver.so,相当于 windows 下 dll文件,*nix下动态库一般使用*.so后缀名,即Shared Object,共享对象。用已提供进程启动后可动态的加载库。

三、让动态加载器发现库文件

编译时加上参数 -L/usr/local/lib/lsystem
这样就编译出了不包含函数代码可执行文件了,但是但你运行时会发现linux动态加载器打不到liblserver.so文件.

可以用ldd 命令查看可执行文件依赖什么共享库:
ldd test
解决方法如下

1. 设置LD_LIBRARY_PATH 环境变量
export LD_LIBRARY_PATH=”$LD_LIBRARY_PATH:.”
2.修改/etc/ld.so.conf文件
一般应用程序的库文件不与系统库文件放在同一个目录下,习上惯是把应用程序的共享库文件放在/usr/local/lib下,新建一个属于自己的目录lserver然后把刚才liblserver.so复制过去就行了
同时在/etc/ld.so.conf中新增一行:
/usr/local/lib/lserver

或者在/etc/ld.so.conf.d中建立一个包含此目录的lserver.conf的文件(debian,ubuntu)
四、最后需要执行ldconfig命令

ldconfig命令的用途是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc /ld.so.cache,此文件保存已排好序的动态链接库名字列表.
ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令.

lserver项目地址:http://code.google.com/p/lserver/

猪八戒威客网

March 16th, 2010

http://zhubajie.com/

早上被我访问出个问题:

转载——10点整笑话

March 15th, 2010

老公: 现在几点?

老婆: 十点。

老公: 整吗?

老婆: 太早了吧,别人都没有睡觉呢!

老公: 我是问十点整吗?

老婆: 十一点再整吧。

老公: 你妈的,我问你是不是1 0点整。

老婆: 你妈的,1 1点在整,你一天不搞我 你不得劲是不是?

老公: 我只是在问,现在是1 0点钟整么?

老婆: 整整整,现在就整