碎碎念,关于一个datastore

最近,想做一个data store,存储一些用户数据。我想越简单越好,不要搞什么分布式,尽力单机解决所有问题,然后找一个机器做replication。但是呢,这个机器所处位置很重要,很容易成为整个网站的瓶颈,所以我还是想尽可能的提高效率。

我要一个什么东西呢? 简单点说,就是一个可持久化的、高效的KV存储。例如腾讯的CMEM服务,或者,mysqld+memcached。我只是举个例子,不一定非要走memcache的接口。每个item都有一个过期时间,超过那个时间之后,应当被删除,否则硬盘会炸掉的。据同事估计,数据量大概是1-2T左右。我觉得我通过压缩手段,能降低到100GB的规模。请求的频率呢,大概是每秒2-3万次读写,而且写入比例非常大,可能是读的2-3倍。我希望能尽可能的把QPS(query per second)做高一些,比如做到10W QPS。

这个问题,如果想最简单的解决方式,那么可能是用一个mysql或者redis这样的数据库,然后尽力优化就行了。MySQL的qps能到多少呢?我之前测试,即便是最简单的update语句,也只有5000左右。client是单线程的。

一个key-value的data store,QPS的瓶颈在哪?Btree/Hash本身?还是网络IO?

为了测试一下RPC的性能,我昨天做了一个非常简单的测试,用ICE写一个特别简单的hello world,服务器端收到请求之后,不做任何处理,立马return 0。服务器端是C++的,客户端是JAVA的。你猜QPS多少?在我自己的笔记本上测试,只有3000。放在服务器上测试,2个intel E5620(4核),只有7-8千。为什么只有这么低呢?因为客户端是单线程的。第一个请求完了之后,才会发第二个请求。于是我在单机上开了20个进程一起跑,大约测试到8万左右的QPS。但是,这个数据我能满意吗?按我实际的运行环境,我这东西只对内网服务,我的client只有10个左右。所以,如果这些client本身不是多线程的,那么我的吞吐量可能无法达到3万。

假设,服务器的内存已经非常大,cache命中率已经足够高,那么通过加CPU,能提高QPS吗?现在绝大多数高性能网络服务器都是单线程模型,所以我才有这个疑问。假如,用epoll做一个echo service,那么单机能跑到多少? Hash这样的结构,非常适合于并发读写,那么,Hash这样的数据库查找操作,和线程上下文切换相比,那么更大?我的直觉是,如果采用connection-per-thread(而不是query-per-thread)的模式,也别用什么epoll,就是简单的bind-listen-select-dispatch模式,再配合一个HASH表,是非常棒的!一定可以把QPS提上去。

数据库本身的效率呢? BerkeleyDB不用费心做什么优化,也能轻松达到每秒10万次以上(假设数据都在/dev/shm里)。当它达不到的时候,瓶颈一定在磁盘IO上。调整cache、换SSD呗。这时候就跟业务本身很有关系 了,比如热点数据占总数据量的比例是多少? 所以,100GB 和1TB是有质的区别的。

最后我在想一个问题,质变与量变。毫无疑问,通过memcache的接口访问Mysql 5.6,要比普通的sql接口要快,因为省去了sql解析的开销。但是呢,究竟快多少?4倍还是10倍?还是100倍?再比如,BerkeleyDB和Mysql相比,性能差多少倍?10倍?50倍?如果在10倍以上,我认为就是有质的差别。10倍以下,可能通过换更好的硬件,比如换Sandy Bridge的CPU,就达到了。在软件层面,每次的性能提升,都是以功能性为代价的。如果BerkeleyDB和InnoDB的性能差不多,那么谁还用BerkeleyDB?大多数都用Mysql去了。(但是panpan这样的追求简洁之美的依然会用BerkeleyDB)

所以啊,有两个问题很关键:

  1. 我需要什么功能
  2. 我需要什么样的性能

只有懂得量身裁衣,才是一个好码农。

此博客中的热门博文

少写代码,多读别人写的代码

在windows下使用llvm+clang

tensorflow distributed runtime初窥