2015-03-31 21:26:53
来 源
中存储网
MySQL
Redis是一个高级的key-value存储系统,类似于memcached,但是又不完全相同,memcached的数据是完全保存在内存中的,而redis支持的数据类型更多,redis既支持将数据保存在内存中(然后定期自动同步到rdb文件中)。

1.Redis介绍
Redis是一个高级的key-value存储系统,类似于memcached,但是又不完全相同,memcached的数据是完全保存在内存中的,而redis支持的数据类型更多,redis既支持将数据保存在内存中(然后定期自动同步到rdb文件中),又可以直接将数据保存到rdbr文件中,此时不用内存保存。
Redis is an advanced key-value store. It is similar to memcached but the dataset is not volatile, and values can be strings, exactly like in memcached, but also lists, sets, and ordered sets. All this data types can be manipulated with atomic operations to push/pop elements, add/remove elements, perform server side union, intersection, difference between sets, and so forth. Redis supports different kind of sorting abilities.
In order to be very fast but at the same time persistent the whole dataset is taken in memory, and from time to time saved on disc asynchronously (semi persistent mode) or alternatively every change is written into an append only file (fully persistent mode). Redis is able to rebuild the append only file in background when it gets too big.
Via: http://code.google.com/p/redis/
Redis的作者是Salvatore Sanfilippo,现在已经加盟Vmware公司。Vmware有可能在它的云计算应用中使用Redis作为存储系统。

A high profile open source developer Salvatore Sanfilippo (@antirez) joined VMware engineering team today. He is the project owner of Redis. Welcome Salvatore!
Via: http://www.doublecloud.org/2010/03/why-is-vmware-intersted-in-redis/
redis目前提供四种数据类型:string,list,set及zset(sorted set)。
a.string是最简单的类型,你可以理解成与Memcached一模一个的类型,一个key对应一个value,其上支持的操作与Memcached的操作类似。但它的功能更丰富。 b.list是一个链表结构,主要功能是 push、pop、获取一个范围的所有值等等。操作中key理解为链表的名字。
c.set是集合,和我们数学中的集合概念相似,对集合的操作有添加删除元素,有对多个集合求交并差等操作。操作中key理解为集合的名字。
d.zset是set的一个升级版本,他在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。操作中key 理解为zset的名字。

2.安装及配置
从redis的下载页面 (http://code.google.com/p/redis/downloads/list)找到redis的最新稳定版本。
debian:/home/software# wget http://redis.googlecode.com/files/redis-1.2.6.tar.gz
--2010-06-21 14:13:22-- http://redis.googlecode.com/files/redis-1.2.6.tar.gz
Resolving redis.googlecode.com... 74.125.153.82
Connecting to redis.googlecode.com|74.125.153.82|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 213341 (208K) [application/x-gzip]
Saving to: `redis-1.2.6.tar.gz'
100%[===============================================>] 213,341 93.6K/s in 2.2s
2010-06-21 14:13:25 (93.6 KB/s) - `redis-1.2.6.tar.gz' saved [213341/213341]
tar zxvf redis-1.2.6.tar.gz
cd redis-1.2.6
直接make即可,不需要执行./configure xxx,makefile文件是现成的。
make
make以后会在当前目录下生成4个可执行文件
redis-benchmark、redis- cli、redis-server、redis-stat
将4个可执行文件及redis的配置文件拷贝到下面的目录下。
mkdir -p /usr/local/redis/bin
mkdir -p /usr/local/redis/etc
cp redis-benchmark redis-cli redis-server redis-stat /usr/local/redis/bin
cp redis.conf /usr/local/redis/etc
修改配置文件redis.conf下面几项配置的值
# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes
# When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
# You can specify a custom pid file location here.
pidfile /usr/local/redis/redis.pid
# Specify the log file name. Also 'stdout' can be used to force
# the demon to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile /usr/local/redis/redis.log
# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes
# The filename where to dump the DB
dbfilename dump.rdb
# For default save/load DB in/from the working directory
# Note that you must specify a directory not a file name.
dir /usr/local/redis/
启动redis
root@debian:/home/software/redis-1.2.6# redis-server /usr/local/redis/etc/redis.conf
New pid: 2479
我们可以看到redis已经启动了,进程id为 2479,监听在6379端口。
root@debian:/home/software/redis-1.2.6# ps -p 2479
PID TTY TIME CMD
2479 ? 00:00:00 redis-server
root@debian:/home/software/redis-1.2.6# netstat -antl | grep 6379
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN
root@debian:/home/software/redis-1.2.6# more /usr/local/redis/redis.pid
2479
root@debian:/home/software/redis-1.2.6# more /usr/local/redis/redis.log
21 Jun 14:43:03 - Server started, Redis version 1.2.6
21 Jun 14:43:03 * WARNING overcommit_memory is set to 0! Background save may fail under low condition memory. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
21 Jun 14:43:03 - The server is now ready to accept connections on port 6379
21 Jun 14:43:04 . 0 clients connected (0 slaves), 412189 bytes in use, 0 shared objects
...
还有几项重要的配置也要理解一下。
a.save <seconds> <changes>
大概意思是大概多少时间,有多少次更新操作,则将数据写到磁盘上。
#
# Save the DB on disk:
#
# save <seconds> <changes>
#
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
#
# In the example below the behaviour will be to save:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
# after 60 sec if at least 10000 keys changed
save 900 1
save 300 10
save 60 10000
b.appendonly
默认情况下(appendonly的值为 no)redis异步将数据从内存导入到磁盘中,但是这种情况下如果电脑突然出现什么问题可能会导致数据丢失。如果将appendonly的值设为yes,则每次对redis操作时将相关的数据写入到appendonly.log文件中,这样数据就不会丢失了,这样虽然安全一些,但是会导致性能降低。
# By default Redis asynchronously dumps the dataset on disk. If you can live
# with the idea that the latest records will be lost if something like a crash
# happens this is the preferred way to run Redis. If instead you care a lot
# about your data and don't want to that a single record can get lost you should
# enable the append only mode: when this mode is enabled Redis will append
# every write operation received in the file appendonly.log. This file will
# be read on startup in order to rebuild the full dataset in memory.
#
# Note that you can have both the async dumps and the append only file if you
# like (you have to comment the "save" statements above to disable the dumps).
# Still if append only mode is enabled Redis will load the data from the
# log file at startup ignoring the dump.rdb file.
#
# The name of the append only file is "appendonly.log"
#
# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
# log file in background when it gets too big.
appendonly no
c.appendfsync
no表示等操作系统进行数据缓存同步到磁盘
always表示每次更新操作后手动调用 fsync()将数据写到磁盘
everysec表示每秒同步一次
# The fsync() call tells the Operating System to actually write data on disk
# instead to wait for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log . Slow, Safest.
# everysec: fsync only if one second passed since the last fsync. Compromise.
#
# The default is "always" that's the safer of the options. It's up to you to
# understand if you can relax this to "everysec" that will fsync every second
# or to "no" that will let the operating system flush the output buffer when
# it want, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting).
appendfsync always
# appendfsync everysec
# appendfsync no
d.maxmemory
分配给redis的最大内存。
在应用中数据使用的内存不要超过在这里指定的内存。
# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys with an
# EXPIRE set. It will try to start freeing keys that are going to expire
# in little time and preserve keys with a longer time to live.
# Redis will also try to remove objects from free lists if possible.
#
# If all this fails, Redis will start to reply with errors to commands
# that will use more memory, like SET, LPUSH, and so on, and will continue
# to reply to most read-only commands like GET.
#
# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
# 'state' server or cache, not as a real DB. When Redis is used as a real
# database the memory usage will grow over the weeks, it will be obvious if
# it is going to use too much memory in the long run, and you'll have the time
# to upgrade. With maxmemory after the limit is reached you'll start to get
# errors for write operations, and this may even lead to DB inconsistency.
#
# maxmemory <bytes>

3. 测试
redis支持的命令真的是非常多,比 memcached协议中支持的命令多很多,需要一段时间的学习。
redis命令一览表:http://code.google.com/p/redis /wiki/CommandReference
web命令行模拟页面: http://try.redis-db.com/
(1)对字符串数据进行操作
a.通过命令redis-cli来操作 redis
root@debian:/home/software/redis-1.2.6# redis-cli set name caihuafeng
OK
root@debian:/home/software/redis-1.2.6# redis-cli get name
caihuafeng
b.通过telnet来操作redis
注意,执行set操作时要指定数据大小,否则get时会报错,这点与memcached协议是一样的。而命令redis-cli则不需要指定数据大小,因为redis-cli本身会自动处理。
Via: http://code.google.com/p/redis/wiki/ProtocolSpecification
root@debian:/home/software/redis-1.2.6# telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get name
$10
caihuafeng
set province 5
hubei
+OK
get province
$5
hubei
数据文件dump.rdb的内容
root@debian:/usr/local/redis# more dump.rdb
REDIS0001name
caihuafenprovincehubeioot
(2)对list数据类型(链表)的操作示例
往链表mylistyst中添加三个元素 a,b,c
rpush mylist 1
a
+OK
rpush mylist 1
b
+OK
rpush mylist 1
c
+OK
显示链表mylistyst的数据类型
type mylist
+list
显示链表mylistyst中的值
lrange mylist 1 3
*3
$1
a
$1
b
$1
c
返回链表mylistyst中的第二个元素
lindex mylist 2
$1
b
将链表mylistyst中的第二个元素b的值设为bb
下面的命令中第一个数字2表示第二个元素的索引,第二个数字2表示要设置值bb的长度为2。
lset mylist 2 2
bb
+OK
显示修改以后链表mylist中的值
lrange mylist 1 3
*3
$1
a
$2
bb
$1
c

(3).对set数据类型(集合)的操作示例
增加三个元素1,2,3到集合set1中
sadd set1 1
1
:1
sadd set1 1
2
:1
sadd set1 1
3
:1
显示set1的数据类型
type set1
+set
增加三个元素1,2,4到集合set2中
sadd set2 1
1
:1
sadd set2 1
2
:1
sadd set2 1
4
:1
显示集合set1里面的元素
smembers set1
*3
$1
3
$1
1
$1
2
显示集合set2里面的元素
smembers set2
*3
$1
4
$1
1
$1
2
求集合set1及set2的交集
sinter set1 set2
*2
$1
1
$1
2
求集合set1及set2的差集
sdiff set1 set2
*1
$1
3

(4)对hash数据类型的操作示例
测试的时候报-ERR unknown command 'hset'的错误,看了redis的帮助,发现只有redis1.3.10及以上版本才支持此功能,我安装的redisrs是1.2.6版本的,所以不支持,操作也是比较简单的。
HSET key field value (Redis >= 1.3.10)

(5)排序
对集合set1中的值进行顺排
sort set1
*3
$1
1
$1
2
$1
3
对集合set1中的值进行倒排
sort set1 desc
*3
$1
3
$1
2
$1
1
对集合set1中的值进行倒排,并取前面两个值,是不是与MySQL的limit有点类似
sort set1 desc limit 0 2
*2
$1
3
$1
2
还有更多更复杂的排序请移步阅读。http://code.google.com /p/redis/wiki/SortCommand

(6)总结
在用telnet对redis进行操作时,在redis的命令一览表中,如果命令的说明里面有value,则一般的操作是在value的位置上加上key对应的字节数,然后输入回车键,再输入值。
SET key value
LPUSH key value
set key lengthrn
valuern
lpush key lengthrn
valuern
例如
set name 10
caihuafeng
rpush mylist 1
a

4.redis主从配置
root@debian:/usr/local/redis/etc# cp redis.conf redis.master.conf
root@debian:/usr/local/redis/etc# cp redis.conf redis.slave.conf
master listen on port 6380
slave listen on port 6381
在配置文件redis.slave.conf中加入
# Master-Slave replication. Use slaveof to make a Redis instance a copy of
# another Redis server. Note that the configuration is local to the slave
# so for example it is possible to configure the slave to save the DB with a
# different interval, or to listen to another port, and so on.
#
# slaveof <masterip> <masterport>
slaveof localhost 6380
启动主从服务,先启动主redis,再启动从 redis,因为从redis要依赖主redis。
root@debian:/usr/local/redis/etc# redis-server redis.master.conf
New pid: 2553
root@debian:/usr/local/redis/etc# redis-server redis.slave.conf
New pid: 2570
root@debian:/usr/local/redis# more redis.master.log
21 Jun 17:56:03 . Accepted 127.0.0.1:47892
21 Jun 17:56:03 - Slave ask for synchronization
21 Jun 17:56:03 - Starting BGSAVE for SYNC
21 Jun 17:56:03 - Background saving started by pid 2571
21 Jun 17:56:03 - DB saved on disk
21 Jun 17:56:03 . 0 clients connected (1 slaves), 412423 bytes in use, 0 shared objects
21 Jun 17:56:03 - Background saving terminated with success
21 Jun 17:56:03 - Synchronization with slave succeeded
root@debian:/usr/local/redis# more redis.slave.log
21 Jun 17:53:49 * Opening TCP port: bind: Address already in use
21 Jun 17:56:01 - Server started, Redis version 1.2.6
21 Jun 17:56:02 * WARNING overcommit_memory is set to 0! Background save may fail under low condition memory. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
21 Jun 17:56:02 - The server is now ready to accept connections on port 6381
21 Jun 17:56:03 . 0 clients connected (0 slaves), 412229 bytes in use, 0 shared objects
21 Jun 17:56:03 - Connecting to MASTER...
21 Jun 17:56:03 - Receiving 10 bytes data dump from MASTER
21 Jun 17:56:03 - MASTER <-> SLAVE sync succeeded
21 Jun 17:56:08 . 1 clients connected (0 slaves), 412382 bytes in use, 0 shared objects
21 Jun 17:56:13 . 1 clients connected (0 slaves), 412382 bytes in use, 0 shared objects
21 Jun 17:56:18 . 1 clients connected (0 slaves), 412382 bytes in use, 0 shared objects

测试主从数据同步
先在主redis从写入一条数据
root@debian:/usr/local/redis# telnet localhost 6380
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set name 10
caihuafeng
+OK
get name
$10
caihuafeng
telnet到从redis后就可以直接看到在主redis中写入的数据了。
root@debian:/usr/local/redis# telnet localhost 6381
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get name
$10
caihuafeng
主从redis对应的数据文件也是一样的。
root@debian:/usr/local/redis# more dump.master.rdb
REDIS0001oot@debian:/usr/local/redis# more dump.slave.rdb
REDIS0001

5.测试maxmemory
当在redis的配置文件中设置maxmemory为20字节时,则进行set操作时,会报如下的错误,说明内存空间不够了,加大maxmemory的值,然后重启redis服务就不会报错了。
debian:/usr/local/redis/etc# grep maxmemory redis.conf
# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
# 'state' server or cache, not as a real DB. When Redis is used as a real
# database the memory usage will grow over the weeks, it will be obvious if
# it is going to use too much memory in the long run, and you'll have the time
# to upgrade. With maxmemory after the limit is reached you'll start to get
# errors for write operations, and this may even lead to DB inconsistency.
#
# maxmemory <bytes>
maxmemory 20
debian:/usr/local/redis# telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
set name 10
-ERR command not allowed when used memory > 'maxmemory'
此服务的配置文件redis.conf里面对应的rdb文件是dump.rdb,而此文件没有生成,难道数据是保存在内存中的?应该是的。
debian:/usr/local/redis# ls -l *.rdb
-rw-r--r-- 1 root staff 29 2010-06-21 18:11 dump.master.rdb
-rw-r--r-- 1 root staff 29 2010-06-21 18:11 dump.slave.rdb
我们首先设置几个值。
set website1 4
1616
+OK
set website2 3
360
+OK
set website3 6
hao123
+OK
过了一段时间以后,发现rdb文件生成了,应该是数据首先保存在内存中,然后定时同步到rdb文件中的。
debian:/usr/local/redis# more dump.rdb
REDIS0001website1website2name
caihuafenwebsite3hao123ebian:/usr/local/redis# ls -l dump.rdb
-rw-r--r-- 1 root staff 72 2010-06-22 11:43 dump.rdb

6.总结
通过以上对redis的使用及测试,发现redis是一个很好的存储系统,特别是在命令行操作上要比memcached、Tokyo Tyrant要强得多、方便得多、支持的数据类型也更多,支持Ruby、Python、PHP、Erlang、Tcl、Perl、Lua、Java、 Scala、C#、C、Javascript、Go等各种主流的语言,是值得在项目中使用的,Yupoo在它们的项目中就使用到了redis(Via),国外使用redis的有代码托管网站github、 Craigslist(分类信息网站的鼻祖)等很多。
以上提到的知识点只是redis很小的一部分功能而已,一般是根据项目需要,需要用到那个功能则去深入了解相应的功能部分,没必要一下子全部掌握得很熟练。在这个容易浮躁的社会,如果少一点浮躁的话,静下心来还是能学到新东西的。

声明: 此文观点不代表本站立场;转载须要保留原文链接;版权疑问请联系我们。