本篇要评测的Nosql产品是Redis,可以把它的功能理解为一个Key-Value的数据结构操作,数据都保存在内存中定期刷新到磁盘,以极高的读写效率而备受关注。国内的新浪微博就大规模的使用了Redis来存储用户关系和计数。
介 绍
按照官方的说法,Redis是用ANSI C开发的,能运行在大多数POSIX(Linux,*BSD,OS X 和Solaris等)系统上,官方没有支持Windows的版本。目前最新的版本是2.2.11,这个版本主要是修复了一个2.2.7版本中遍历方式优化 带来的一个bug。
和普通的Key-Value结构不同,Redis的Key支持灵活的数据结构,除了strings,还有hashes、lists、 sets 和sorted sets等结构。正是这些灵活的数据结构,丰富了Redis的应用场景,能满足更多业务上的灵活存储需求。
Redis的数据都保存在内存中,而且底层实现上是自己写了epoll event loop部分,而没有采用开源的libevent等通用框架,所以读写效率很高。为了实现数据的持久化,Redis支持定期刷新(可通过配置实现)或写日志的方式来保存数据到磁盘。
安装和使用
由于没有第三方的包依赖关系,Redis的安装十分简单:
$ wget http://redis.googlecode.com/files/redis-2.2.11.tar.gz
$ tar xzf redis-2.2.11.tar.gz
$ cd redis-2.2.11
$ make
这样就安装完毕了,执行src目录下的redis-server可以启动Redis进程,不过最好先配置一下redis.conf文件,常用的几个要注意的参数如下:
daemonize yes
指定Redis以守护进程的方式运行。
pidfile /home/banping/redis/redis.pid
当Redis以守护进程方式运行时,把pid写入指定的文件。
port 6379
指定监听端口,默认端口为6379。
bind 192.168.0.35
绑定的主机IP地址。
logfile stdout
指定日志的记录方式,默认为标准输出。
databases 16
save
Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改的时候,同步数据到磁盘文件。
rdbcompression yes
指定存储至本地数据库时是否压缩数据,默认为yes。
dbfilename dump.rdb
dir /home/banping/redis/data
指定本地数据库存放目录。
requirepass foobared
设置Redis连接密码,默认关闭。
maxclients 128
设置最大客户端连接数,默认无限制。
maxmemory
指定Redis能使用的最大内存。
其他更详细的参数说明请参见官方文档。修改完配置文件后,我们可以用指定的配置文件启动Redis服务:
[root@localhost redis-2.2.10]# src/redis-server /home/banping/redis/redis-2.2.11/redis.conf
这样一个redis服务进程就启动了,它监听6379端口来提供服务。
测试说明
一、测试环境
MongoDB部署在一台PC 服务器上,配置如下:
CPU为Xeon 2.80GHz *4
内存为4G
硬盘为一块400G SATA盘
操作系统为64位CentOS 5.3版本
二、测试方法
这里仍然采用PHP客户端进行测试,Redis官方推荐了两个PHP客户端,一个是PHP程序包Predis,另一个是C开发的扩展包 PHPredis,我们这里采用后者,网址为https://github.com/nicolasff/PHPredis ,可以编译到PHP运行环境中来使用。
为了不对测试服务器产生额外的影响,测试客户端部署在另外一台独立的服务器上,运行的PHP的版本是5.3.5,web server是Nginx 0.8.54,通过fastcgi的方式调用PHP服务。使用apache ab工具实现多个请求和并发操作。
测试过程中就使用上文提到的已经启动的Redis服务,首先是进行写操作,通过500个请求,每个请求写入10000条记录,并发度为2来共写入500 万条数据,key为数字1到5000000,value大小为100个字节。然后是读操作,也是用500个请求,每个请求随机根据key值读出10000 条记录,并发度为10共读出500万条记录,评测的重点是写入和读出数据的时间,以及在此过程中服务器的资源使用情况。
测试结果及总结
一、写操作
成功写入500万条记录,共耗时524秒,平均每秒写入数据9542笔。磁盘上的数据文件大小134M。写入过程中,服务器内存、CPU和磁盘等资源使用情况如下图所示:
可见,内存使用平稳上升,最后占用140M左右,主要用来缓存数据,对比数据文件的大小可以设想,在操作系统内 存可用的情况下,内存的分配和数据文件的大小是大致相当的。内存占用会有临时的超过实际占用的几个点,而且会马上释放掉,cpu和磁盘IO都表现出周期性 的上下波动,估计这些和Redis刷新数据到磁盘的实现机制有关,在高点的时候正好是数据写入磁盘的过程。总体来说占用资源很少,表现也很平稳。
二、读操作
成功读出500万条记录,共耗时184秒,平均每秒读出数据27174笔。
读数据过程中没有发生磁盘IO。cpu有所消耗,Idle值稳定在77左右,等待cpu资源的进程一直是1个。内存表现平稳没有波动。
通过以上测试结果可以看出,Redis数据操作都在内存完成,定期刷新到磁盘,占用的磁盘空间和内存大小由实际的数据量决定,在内存可用的情况下二者是 一致的。从功能角度看Redis高效的读写效率和丰富的数据结构能满足很多互联网应用场景的需求,而且在高负载的情况下,数据内存化是趋势,总体来说 Redis虽然还在不断发展之中,代码量也不多,但是一个轻量级的很有潜力的Nosql产品,肯定会有越来越多的成功案例。