年底的时候开始尝试在重构的项目中使用redis,现在项目稳定运行也有一段时间了,这里做一下阶段性总结。
一、简介
首先,redis是什么意思呢,官方文档的FAQ里给出了答案:It means REmote DIctionary Server.也就是说,它是一个可提供远程调用的字典服务器,从名字就可以看出,它起码得是一个k-v服务器吧:),事实上,它除了支持get、set、del等基本操作之外,还支持许多更复杂一些的操作,这也是它优于memcached等其他k-v组件的地方。
Redis是一个高级的k-v服务器,既可以做cache使用,也可以做存储使用,同时,它也可以被称作是一个数据结构服务器。为什么说它可以叫数据结构服务器呢?因为它支持几种数据结构,作为key-value里的value这一项,它可以存储strings, hashes, lists, sets, sorted sets, bitmaps以及hyperloglogs等数据结构,同时,针对不同的数据结构,Redis专门提供了一些特别的操作,使得我们可以使用get set之外的一些操作,例如你可以对两个set取交集并返回结果。
二、安装和启动
Redis的安装非常简单,从官网下载最新的稳定版客户端,make就可以了:
$ wget http://download.redis.io/releases/redis-2.8.19.tar.gz $ tar xzf redis-2.8.19.tar.gz $ cd redis-2.8.19 $ make
启动也非常简单,编译好的二进制文件会生成在src目录下,直接执行,即可使用默认配置启动redis服务:
$ src/redis-server
这样服务就启动起来了,redis默认监听6379端口,我们可以使用客户端(redis-cli)访问并测试它:
$ src/redis-cli redis> set foo bar OK redis> get foo "bar"
更复杂的配置设置我们在后边再介绍。
三、基本使用举例
想要快速了解redis的使用方法,强烈推荐官网的一篇文章Writing a simple Twitter clone with PHP and Redis(http://redis.io/topics/twitter-clone),如果不熟悉php语法没有关系,php的client基本上就是把redis的命令原封不动的封装了,该文章从实战的角度描述了几种数据结构的使用方法以及在实际使用过程中应该如何设计自己的存储方式。这里我们简单介绍几种数据结构的使用方法:
3.1 string
String是最基本的数据结构了,如果单纯的使用string,那么redis与普通的k-v数据库并无区别,无非就是get、set,下面我们看一下string的基本操作:
> set mykey somevalue OK > get mykey "somevalue"
当执行set的时候,如果”mykey”这个key下原来没有值,则会把”somevalue”存进去,否则下存储的值会被覆盖。
如果只提供get、set,那redis就不是redis了,对于一个key,我们还可以使用INCR,DECR来使数值类型的值增加或减少,还有MGET命令,可以同时获取多个key的值,这在实际使用过程中都会非常有用,例如当你需要同时获取多个数值时,只要一次调用MGET即可,大幅减少网络开销。
3.2 hashes
接下来我们看hash,第一反应,我们可能会想,刚才的string不就是hash吗,从key映射到value。事实上,redis这里说的hash,相当于是对于刚才的string形式的一种嵌套,相当于是我们有一个hash的对象,这个对象的名字叫做key,而它的值又是一个hash,而它的值的key,在redis里叫做field,那么我们就可以了解hash的插入数据的命令了:
> hset user:1000 username OK > hget user:1000 username "antirez"
Hash也可以同时写入多个值,使用HMSET命令即可:
> hmset user:1000 username antirez birthyear 1977 verified 1 OK
类似的,同时读取多个值的时候也可以用HMGET命令,但是需要注意的是使用HMGET获取的时候,一次只能读取同一个key下的多个field值,而不能获取不同的key下的不同field值,如果想获取不同key下不同field值,可以使用redis的pipeline方式获取,从而减少开销。
3.3 sorted sets
Sorted set是一种高级的set,redis本身也支持set,但是我们这里直接讲sorted set吧,它相比普通的set,多了一个score项,也即当插入数据的时候,每一个值都可以赋予它一个score,那么score是做什么用的呢?sorted set,顾名思义,就是可以根据score进行排序了,当我们取出来的时候就可以看到,这个列表是排好序的,这个功能非常的有用,例如当我们想要开发一个排行榜的时候,直接插入榜单项和排名分数就可以了,亦或是要开发一个微博系统时,使用它来存储timeline,使用消息发表时间作为score,那么timeline自然就是排好序的了,而且再利用redis本身提供的取交集或并集功能,这使得业务层的开发量极大的减少,下面我们看一下命令示例:
> zadd hackers 1940 "Alan Kay" (integer) 1 > zadd hackers 1957 "Sophie Wilson" (integer 1) > zadd hackers 1953 "Richard Stallman" (integer) 1 > zadd hackers 1949 "Anita Borg" (integer) 1 > zadd hackers 1965 "Yukihiro Matsumoto" (integer) 1 > zadd hackers 1914 "Hedy Lamarr" (integer) 1 > zadd hackers 1916 "Claude Shannon" (integer) 1 > zadd hackers 1969 "Linus Torvalds" (integer) 1 > zadd hackers 1912 "Alan Turing" (integer) 1
读取的时候使用ZRANGE或者ZREVRANGE,顾名思义就是正序或反序读取:
> zrange hackers 0 -1 withscores
1) "Alan Turing"
2) "1912"
3) "Hedy Lamarr"
4) "1914"
5) "Claude Shannon"
6) "1916"
7) "Alan Kay"
8) "1940"
9) "Anita Borg"
10) "1949"
11) "Richard Stallman"
12) "1953"
13) "Sophie Wilson"
14) "1957"
15) "Yukihiro Matsumoto"
16) "1965"
17) "Linus Torvalds"
18) "1969"
其中withscores是告诉redis是否要返回score项,如果不带此参数则只返回人名列表,非常的方便。
3.4 小结
Redis提供非常丰富的命令可供使用,使得我们可以很方便的对存储数据进行一些高级的操作,而不是仅仅把它当作一个k-v的存储数据,这样可以从一定程度上减少我们的业务复杂性。
Redis命令可以在官网查询到(http://redis.io/commands),在此不一一列举。
四、配置与部署
4.1 持久化
Redis提供两种持久化的方式,使得数据可以落到磁盘上,避免服务崩溃或者机器重启后数据丢失,它们分别是AOF和RDB。
AOF相当于我们服务中通常使用的binlog,每当有写请求过来的时候,redis都会把这个请求写入到AOF文件中,当redis崩溃时,可以读取AOF文件从而重建数据。
RDB又叫snapshoting,也就是快照,相当于我们服务中经常用到的把数据从共享内存dump到磁盘上的操作。
这两个选项均可以在配置文件中配置,redis提供了一个配置文件模版,在redis文件夹下的redis.conf文件,当使用配置文件启动redis时,在redis后边加一个配置文件的参数即可:
src/redis-cli redis.conf
想要打开AOF功能,则可以修改配置文件中的appendonly项为yes,并指定appendfilename为aof的文件名,注意这里只是配置文件名,文件路径需要修改dir配置项,这个配置项同样应用于RDB文件。
RDB功能是默认打开的,它受配置文件中的save项影响:
save 900 1 save 300 10 save 60 10000
这里解释一下这几个选项的意思:SAVE N M代表每N秒至少有M个变化的时候,才进行rdb操作,那么上边的三个选项意思是,当60秒内有10000个变化时,就写磁盘,而当300秒内有10个变化时,也要写磁盘,如果写入实在不频繁,那么900秒内,如果有一个变化,也要写一次。
除了自动化的方式,我们也可以手动调用BGSAVE命令,强制执行数据备份,但是这个命令从字面上来看貌似是background的,但是实际上,也会造成服务阻塞!
需要注意的是,AOF功能可以开启压缩机制,当AOF文件过大时,可以进行压缩;但是这个操作是会阻塞进程的,所以慎重使用!RDB文件也是同样,当执行写RDB操作时,进程也是阻塞的,这两个地方是redis比较让人头疼的地方,目前并没有发现太完美的解决方案。
4.2 主备同步
主备同步的设置比较简单,在配置文件中配置slavof选项:
slaveof <masterip> <masterport>
redis启动的时候就会跟主机建立连接,然后主机会把数据同步过来,但是要注意的是,这个过程也是阻塞的,服务在这个时间内也不可访问。
4.3 小结
Redis提供了简单的持久化的方式,但是它阻塞的方式往往会造成一定时间内的服务不可用,所以在选型的时候要结合自己的业务情况再做决定应该使用怎样的配置。