Hello,Redis (memcached的姐妹篇)
分类:技术知识2010-11-1614:05
Redis和memcached类似,都提供了key-value的方便操作,但是redis解决了memcached没有存储的问题。当然开源的MemcacheDB在memcached基础上也提供了存储的功能。
NoSQL正试图打破关系数据型数据库一统天下的局面。Redis也是NoSQL的一种尝试。Redis是什么?其网站上如是说:
Apersistentkey-valuedatabasewithbuilt-innetinterfacewritteninANSI-CforPosixsystems
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-clisetkeyvalue
OK
>./redis-cligetkey
value
在上面的这个会话里面,我们通过设置的一个键值对(key和value),然后,用键值取回其对应的值,非常简单。除了最简单的键值对,Redis还支持list、set和有序的set。下面的会话是对list的操作:
>./redis-clilpushlist1
OK
>./redis-clilpushlist2
OK
>./redis-clilrangelist0-1
1.2
2.1
>./redis-clirpushlist3
OK
>./redis-clilrangelist0-1
1.2
2.1
3.3
这里的lpush命令在list的头部添加元素,rpush命令在list的尾部添加元素,而lrange用来查询list里面的元素。
上面我们用的命令行对Redis进行操作,实际上,Redis本身就是具备网络接口的数据库,它有着自己的协议,一种简单的文本协议。这个协议本身并不复杂,只要实现了这个协议就可以与Redis进行互联互通了,所以,Redis有着不同语言的客户端实现,而上面用到的命令行也是用同样的协议实现的。
通过以最普通的telnet直连Redis,我们稍微了解一下这个协议。
>telnetlocalhost6379
这里的6379是Redis的缺省端口,下面是一段简单的会话:
SETkey5
value
+OK
GETkey
$5
value
QUIT
这段会话等同上面命令行的第一段会话。SET是命令字,key是键值,5是随后值的长度,value就是值的内容,这就是我们发送的内容,+OK是服务器端给出的应答,告诉我们操作成功。然后,我们获取key对应的值,GET是命令字,key是键值,之后是服务器给出的应答,$5是值的长度,value是值的内容。最后的QUIT是断开连接的命令字。
如此简单的Redis,不妨把它当做了解NoSQL的起步台阶。
Redis的介绍
数据库主要类型有对象数据库,关系数据库,键值数据库等等,对象数据库太超前了,现阶段不提也罢;关系数据库就是平常说的MySQL,PostgreSQL这些熟的不能再熟的东西,至于键值数据库则是本文要着重说的,其代表主要有MemcacheDB,TokyoCabinet等等。
Redis本质上也是一种键值数据库的,但它在保持键值数据库简单快捷特点的同时,又吸收了部分关系数据库的优点。从而使它的位置处于关系数据库和键值数据库之间。Redis不仅能保存Strings类型的数据,还能保存Lists类型(有序)和Sets类型(无序)的数据,而且还能完成排序(SORT)等高级功能,在实现INCR,SETNX等功能的时候,保证了其操作的原子性,除此以外,还支持主从复制等功能。
详细描述参见官方手册,同时,官方提供了一个名为Retwis的项目的源代码,可以对照着官方介绍学习,注意其中关于DataLayout的描述,其他没什么。
项目实践中,多以关系数据库为主,不过合理的使用Redis这样的键值数据库,往往能扬长避短,比如说实现一个类似消息队列的功能,对MySQL来说,除非使用Q4M,否则很难满足高并发请求,不过对Redis来说,通过内建的Lists支持,消息队列就是小菜一碟。
Redis的安装
tarzxvfredis-version.tar.gz
cdredis-version
make
由于没有makeinstall,所以得把源代码目录里的关键文件手动复制到适当的位置:
cpredis.conf/etc/
cpredis-benchmarkredis-cliredis-server/usr/bin/
如果内存情况比较紧张的话,需要设定内核参数:
echo1>/proc/sys/vm/overcommit_memory
然后编辑redis.conf配置文件(/etc/redis.conf),按需求做出适当调整,比如:
daemonizeyes
logfile/dev/null
如果要记录日志的话,最好先调整loglevel到一个合适的级别,然后设定logfile,如果不需要,则可以像上面这样直接把日子丢弃到/dev/null里,还有一点,缺省情况下,数据文件dump.rdb会被生成到当前目录,可以通过dir参数设定合适的目录。
此外,如果你决定把Redis用于产品环境,还要注意maxmemory选项,因为Redis在启动时会把所有数据加载到内存中,所以设定maxmemory相对安全。
接下来直接启动服务就可以了,只有配置文件一个参数:
redis-server/etc/redis.conf
确认运行了之后,可以用redis-benchmark命令测试看看,还可以通过redis-cli命令实际操作一下,比如:
redis-clisetfoobar
OK
redis-cligetfoo
bar
在设置键对应的值的时候,按照协议的规定是要提供数据大小这个参数的,上面的redis-cli命令之所以没有提供这个参数是因为redis-cli本身进行了封装。
可以通过telnet来验证一点:
telnet127.0.0.16379
Trying127.0.0.1...
Connectedtolocalhost.localdomain(127.0.0.1).
Escapecharacteris'^]'.
setfoo3
bar
+OK
getfoo
$3
bar
^]
telnet>quit
Connectionclosed.
更多命令介绍参考文档介绍。
Redis源代码里附带了多种客户端的扩展,比如说php(client-libraries/php),这是一个纯PHP的实现方案,也有二进制版本的实现(phpredis)。其他语言即便没有现成的扩展实现,也可以自己按照协议规范写一个扩展,应该不是什么难事。
Redis内存要求很高,如果你的数据量很大的话,可能会导致系统使用swap,这会使性能急剧下降。此时更好的方法是通过consistenthashing把数据分布到多个服务器上,文档上给出了简单的例子解释:
ForexampleimaginetohaveNRedisservers,server-0,server-1,...,server-N.Youwanttostorethekey"foo",what'stherightserverwheretoput"foo"inordertodistributekeysevenlyamongdifferentservers?Justperformthecrc=CRC32("foo"),thenservernum=crc%N(therestofthedivisionforN).Thiswillgiveanumberbetween0andN-1foreverykey.Connecttothisserverandstorethekey.
Redis
分享到编辑文章
章节
收起
1简介2性能3安装Redis、Redis启动参数介绍4redis数据结构5redis数据存储6redis主从配置7redis起步(链接整理)84.利用Redis构建简单的微博系统
简介
Redis是一个key-value存储系统。和Memcached类似,但是解决了断电后数据完全丢失的情况,而且她支持更多无化的value类型,除了和string外,还支持lists(链表)、sets(集合)和zsets(有序集合)几种数据类型。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
性能
下面是官方的bench-mark数据:
Thetestwasdonewith50simultaneousclientsperforming100000requests.
ThevalueSETandGETisa256bytesstring.
TheLinuxboxisrunningLinux2.6,it’sXeonX33202.5Ghz.
Textexecutedusingtheloopbackinterface(127.0.0.1).
Results:about110000SETspersecond,about81000GETspersecond.
安装Redis、Redis启动参数介绍
3.1.1.获取源码、解压、进入源码目录:
wgethttp://redis.googlecode.com/files/redis-1.2.6.tar.gz
tarxzfredis-1.2.6.tar.gz
cdredis-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
cpredis-serverredis-cliredis-benchmarkredis-stat/usr/local/redis/bin/
cpredis.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等待系统自己同步)
下面是一个略做修改后的配置文件内容:
daemonizeyes
pidfile/usr/local/redis/var/redis.pid
port6379
timeout300
logleveldebug
logfile/usr/local/redis/var/redis.log
databases16
save9001
save30010
save6010000
rdbcompressionyes
dbfilenamedump.rdb
dir/usr/local/redis/var/
appendonlyno
appendfsyncalways
glueoutputbufyes
shareobjectsno
shareobjectspoolsize1024
将上面内容写为redis.conf并保存到/usr/local/redis/etc/目录下
然后在命令行执行:
/usr/local/redis/bin/redis-server/usr/local/redis/etc/redis.conf
即可在后台启动redis服务,这时你通过
telnet127.0.0.16379
即可连接到你的redis服务。
redis数据结构
redis的作者antirez曾笑称其为一个数据结构服务器(datastructuresserver),我认为这是一个非常准确的表述,redis的所有功能就是将数据以其固有的几种结构保存,并提供给用户操作这几种结构的接口。我们可以想象我们在各种语言中的那些固有数据类型及其操作。
redis目前提供四种数据类型:string,list,set及zset(sortedset)。
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文件三部分,配置文件中有三个参数对其进行配置。
savesecondsupdates,save配置,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。
appendonlyyes/no,appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。
appendfsyncno/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构建简单的微博系统
具体例子见官方文档:
《Acasestudy:DesignandimplementationofasimpleTwittercloneusingonlytheRediskey-valuestoreasdatabaseandPHP》
体验新版博客