Hello,Redis (memcached的姐妹篇)

分类: 技术知识 2010-11-16 14:05
Redis和memcached类似,都提供了key-value的方便操作,但是redis解决了memcached没有存储的问题。当然开源的MemcacheDB在memcached基础上也提供了存储的功能。



NoSQL正试图打破关系数据型数据库一统天下的局面。Redis也是NoSQL的一种尝试。Redis是什么?其网站上如是说:
  A persistent key-value database with built-in net interface written in ANSI-C for Posix systems

Redis最值得拿出来说事的优点就是“快”!Github就用了Redis为自己加速。

我们选择下载稳定的发布版:
  http://code.google.com/p/redis/downloads/list
也可以直接获取源码:
  http://github.com/antirez/redis

现在的redis与一般的C开源项目相比,非常简单,只有很少的一些文件。它的构建过程也不像其它的项目那些,需要先配置再构建。它只有一个简单的makefile,构建它,只要make一下即可。当然,正如其声称的那样,目前redis只是为Posix系统而打造,所以,如果想在Windows上构建,也许Cygwin是个选择。

先来做一下简单的体验,启动redis的服务器端:
  > ./redis-server

redis本身还附带了一个命令行的客户端,用它就可以对redis本身进行测试:
  > ./redis-cli set key value
  OK
  > ./redis-cli get key
  value

在上面的这个会话里面,我们通过设置的一个键值对(key和value),然后,用键值取回其对应的值,非常简单。除了最简单的键值对,Redis还支持list、set和有序的set。下面的会话是对list的操作:
  > ./redis-cli lpush list 1
  OK
  > ./redis-cli lpush list 2
  OK
  > ./redis-cli lrange list 0 -1
  1. 2
  2. 1
  > ./redis-cli rpush list 3
  OK
  > ./redis-cli lrange list 0 -1
  1. 2
  2. 1
  3. 3
这里的lpush命令在list的头部添加元素,rpush命令在list的尾部添加元素,而lrange用来查询list里面的元素。

上面我们用的命令行对Redis进行操作,实际上,Redis本身就是具备网络接口的数据库,它有着自己的协议,一种简单的文本协议。这个协议本身并不复杂,只要实现了这个协议就可以与Redis进行互联互通了,所以,Redis有着不同语言的客户端实现,而上面用到的命令行也是用同样的协议实现的。

通过以最普通的telnet直连Redis,我们稍微了解一下这个协议。
  > telnet localhost 6379
这里的6379是Redis的缺省端口,下面是一段简单的会话:
  SET key 5
  value
  +OK
  GET key
  $5
  value
  QUIT
这段会话等同上面命令行的第一段会话。SET是命令字,key是键值,5是随后值的长度,value就是值的内容,这就是我们发送的内容,+OK是服务器端给出的应答,告诉我们操作成功。然后,我们获取key对应的值,GET是命令字,key是键值,之后是服务器给出的应答,$5是值的长度,value是值的内容。最后的QUIT是断开连接的命令字。

如此简单的Redis,不妨把它当做了解NoSQL的起步台阶。

   





Redis的介绍

数据库主要类型有对象数据库,关系数据库,键值数据库等等,对象数据库太超前了,现阶段不提也罢;关系数据库就是平常说的MySQL,PostgreSQL这些熟的不能再熟的东西,至于键值数据库则是本文要着重说的,其代表主要有MemcacheDB,Tokyo Cabinet等等。

Redis本质上也是一种键值数据库的,但它在保持键值数据库简单快捷特点的同时,又吸收了部分关系数据库的优点。从而使它的位置处于关系数据库和键值数据库之间。Redis不仅能保存Strings类型的数据,还能保存Lists类型(有序)和Sets类型(无序)的数据,而且还能完成排序(SORT)等高级功能,在实现INCR,SETNX等功能的时候,保证了其操作的原子性,除此以外,还支持主从复制等功能。

详细描述参见官方手册,同时,官方提供了一个名为Retwis的项目的源代码,可以对照着官方介绍学习,注意其中关于Data Layout的描述,其他没什么。

项目实践中,多以关系数据库为主,不过合理的使用Redis这样的键值数据库,往往能扬长避短,比如说实现一个类似消息队列的功能,对MySQL来说,除非使用Q4M,否则很难满足高并发请求,不过对Redis来说,通过内建的Lists支持,消息队列就是小菜一碟。

Redis的安装

tar zxvf redis-version.tar.gz
cd redis-version
make

由于没有make install,所以得把源代码目录里的关键文件手动复制到适当的位置:

cp redis.conf /etc/
cp redis-benchmark redis-cli redis-server /usr/bin/

如果内存情况比较紧张的话,需要设定内核参数:

echo 1 > /proc/sys/vm/overcommit_memory

然后编辑redis.conf配置文件(/etc/redis.conf),按需求做出适当调整,比如:

daemonize yes
logfile /dev/null

如果要记录日志的话,最好先调整loglevel到一个合适的级别,然后设定logfile,如果不需要,则可以像上面这样直接把日子丢弃到/dev/null里,还有一点,缺省情况下,数据文件dump.rdb会被生成到当前目录,可以通过dir参数设定合适的目录。

此外,如果你决定把Redis用于产品环境,还要注意maxmemory选项,因为Redis在启动时会把所有数据加载到内存中,所以设定maxmemory相对安全。

接下来直接启动服务就可以了,只有配置文件一个参数:

redis-server /etc/redis.conf

确认运行了之后,可以用redis-benchmark命令测试看看,还可以通过redis-cli命令实际操作一下,比如:

redis-cli set foo bar
OK
redis-cli get foo
bar

在设置键对应的值的时候,按照协议的规定是要提供数据大小这个参数的,上面的redis-cli命令之所以没有提供这个参数是因为redis-cli本身进行了封装。

可以通过telnet来验证一点:

telnet 127.0.0.1 6379
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
set foo 3
bar
+OK
get foo
$3
bar
^]
telnet> quit
Connection closed.

更多命令介绍参考文档介绍。

Redis源代码里附带了多种客户端的扩展,比如说php(client-libraries/php),这是一个纯PHP的实现方案,也有二进制版本的实现(phpredis)。其他语言即便没有现成的扩展实现,也可以自己按照协议规范写一个扩展,应该不是什么难事。

Redis内存要求很高,如果你的数据量很大的话,可能会导致系统使用swap,这会使性能急剧下降。此时更好的方法是通过consistent hashing把数据分布到多个服务器上,文档上给出了简单的例子解释:

For example imagine to have N Redis servers, server-0, server-1, ..., server-N. You want to store the key "foo", what's the right server where to put "foo" in order to distribute keys evenly among different servers? Just perform the crc = CRC32("foo"), then servernum = crc % N (the rest of the division for N). This will give a number between 0 and N-1 for every key. Connect to this server and store the key.

Redis


分享到编辑文章



章节
收起
1 简介2 性能3 安装Redis、Redis启动参数介绍4 redis数据结构5 redis数据存储6 redis主从配置7 redis起步(链接整理)8 4.利用Redis构建简单的微博系统




简介
Redis是一个key-value存储系统。和Memcached类似,但是解决了断电后数据完全丢失的情况,而且她支持更多无化的value类型,除了和string外,还支持lists(链表)、sets(集合)和zsets(有序集合)几种数据类型。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。



性能
下面是官方的bench-mark数据:

The test was done with 50 simultaneous clients performing 100000 requests.
The value SET and GET is a 256 bytes string.
The Linux box is running Linux 2.6, it’s Xeon X3320 2.5Ghz.
Text executed using the loopback interface (127.0.0.1).
Results: about 110000 SETs per second, about 81000 GETs per second.



安装Redis、Redis启动参数介绍
3.1.1.获取源码、解压、进入源码目录:
wget http://redis.googlecode.com/files/redis-1.2.6.tar.gz
tar xzf redis-1.2.6.tar.gz
cd redis-1.2.6
3.1.2.编译生成可执行文件:
由于makefile文件已经写好,我们只需要直接在源码目录执行make命令进行编译即可:
make
make命令执行完成后,会在当前目录下生成本个可执行文件,分别是redis-server、redis-cli、redis-benchmark、redis-stat,它们的作用如下:
redis-server:Redis服务器的daemon启动程序
redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作
redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
redis-stat:Redis状态检测工具,可以检测Redis当前状态参数及延迟状况
3.1.3.建立Redis目录(非必须)
这个过程不是必须的,只是为了将Redis相关的资源统一管理而进行的操作。
执行以下命令建立相关目录并拷贝相关文件至目录中:
sudo -s
mkdir -p /usr/local/redis/bin
mkdir -p /usr/local/redis/etc
mkdir -p /usr/local/redis/var
cp redis-server redis-cli redis-benchmark redis-stat /usr/local/redis/bin/
cp redis.conf /usr/local/redis/etc/

3.2.Redis配置参数详解
在我们成功安装Redis后,我们直接执行redis-server即可运行Redis,此时它是按照默认配置来运行的(默认配置甚至不是后台运行)。我们希望Redis按我们的要求运行,则我们需要修改配置文件,Redis的配置文件就是我们上面第二个cp操作的redis.conf文件,目前它被我们拷贝到了/usr/local/redis/etc/目录下。修改它就可以配置我们的server了。如何修改?下面是redis.conf的主要配置参数的意义:

daemonize:是否以后台daemon方式运行
pidfile:pid文件位置
port:监听的端口号
timeout:请求超时时间
loglevel:log信息级别
logfile:log文件位置
databases:开启数据库的数量
save * *:保存快照的频率,第一个*表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。
rdbcompression:是否使用压缩
dbfilename:数据快照文件名(只是文件名,不包括目录)
dir:数据快照的保存目录(这个是目录)
appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。
appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)
下面是一个略做修改后的配置文件内容:
daemonize yes
pidfile /usr/local/redis/var/redis.pid
port 6379
timeout 300
loglevel debug
logfile /usr/local/redis/var/redis.log
databases 16
save 900 1
save 300 10
save 60 10000
rdbcompression yes
dbfilename dump.rdb
dir /usr/local/redis/var/
appendonly no
appendfsync always
glueoutputbuf yes
shareobjects no
shareobjectspoolsize 1024

将上面内容写为redis.conf并保存到/usr/local/redis/etc/目录下

然后在命令行执行:
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

即可在后台启动redis服务,这时你通过
telnet 127.0.0.1 6379
即可连接到你的redis服务。



redis数据结构
redis 的作者antirez曾笑称其为一个数据结构服务器(data structures server),我认为这是一个非常准确的表述,redis的所有功能就是将数据以其固有的几种结构保存,并提供给用户操作这几种结构的接口。我们可以想象我们在各种语言中的那些固有数据类型及其操作。
redis目前提供四种数据类型:string,list,set及zset(sorted set)。
string是最简单的类型,你可以理解成与Memcached一模一个的类型,一个key对应一个value,其上支持的操作与Memcached的操作类似。但它的功能更丰富。
list是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。
set是集合,和我们数学中的集合概念相似,对集合的操作有添加删除元素,有对多个集合求交并差等操作。操作中key理解为集合的名字。
zset是set的一个升级版本,他在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。操作中key理解为zset的名字。
在官网上给出了所有支持的接口列表,并副副附有详细的介绍,地址:
http://code.google.com/p/redis/wiki/CommandReference
另外,作者还提供了一个非常贴心的web命令行模拟页面,供初学者试用redis,地址:
http://try.redis-db.com/



redis数据存储
redis的快速是业内闻名的,但是我想说,这个速度还是有一定水分的,且看下文。
redis的存储分为内存存储、磁盘存储和log文件三部分,配置文件中有三个参数对其进行配置。
save seconds updates,save配置,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。
appendonly yes/no ,appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。
appendfsync no/always/everysec ,appendfsync配置,no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。



redis主从配置
redis支持master-slave的主从配置,配置方法是在从机的配置文件中指定slaveof参数为主机的ip和port即可,原理上来说,是从机请求主机的方式,按照tokyotyrant的做法,是可以实现主-主,主-从等灵活形式的,而redis只能支持主从,不能支持主-主,可能是其同步原理的差异所致。(本人还没有试过将两台机器的slaveof参数互指的情况是否可实现主-主。)



redis起步(链接整理)
项目首页,下方是各种语言支持列表:
http://code.google.com/p/redis/
作者在wiki中给出了一个非常好的例子,以使我们可以快速上手,地址:
http://code.google.com/p/redis/wiki/TwitterAlikeExample
同时作者推荐的另一个教程,地址:
http://labs.alcacoop.it/doku.php?id=articles:redis_land
一个redis爱好者创建的相关问题讨论网站:
http://www.rediscookbook.org/



4.利用Redis构建简单的微博系统
具体例子见官方文档:
《A case study: Design and implementation of a simple Twitter clone using only the Redis key-value store as database and PHP》

体验新版博客

你可能感兴趣的:(memcached)