一、引言
缓存就是数据交换的缓冲区(称作Cache)——摘自百度百科。无论是在计算机硬件体系结构还是软件体系结构中,缓存都是提高系统性能的重要手段,应用十分广泛,如:CPU多级缓存、磁盘缓存、操作系统缓存、数据库缓存、浏览器缓存等。互联网的高速发展不断挑战WEB系统的性能极限,随着分布式集群应用的日益广泛,对缓存技术的要求也越来越高,除高性能外,还要满足动态扩展性、高可用性等
二、简介
Redis —— REmote DIctionary Server,可以直接理解为远程字典服务,也就是基于Key-Value模式的Memcached+Database Persistence
Redis的键值可以包括字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等数据类型。 对于这些数据类型,你可以执行原子操作。例如:对字符串进行附加操作(append);递增哈希中的值;向列表中增加元素;计算集合的交集、并集与差集等
为了获得优异的性能,Redis采用了内存中(in-memory)数据集(dataset)的方式。根据使用场景的不同,你可以每隔一段时间将数据集转存到磁盘上来持久化数据,或者在日志尾部追加每一条操作命令
Redis同样支持主从复制(master-slave replication),并且具有非常快速的非阻塞首次同步(non-blocking first synchronization)、网络断开自动重连等功能。同时Redis还具有其它一些特性,其中包括简单的check-and-set机制、pub/sub和配置设置等,以便使得Redis能够表现得更像缓存(cache)
Redis还提供了丰富的客户端,以便支持现阶段流行的大多数编程语言。详细的支持列表可以参看Redis官方文档:http://redis.io/clients。Redis自身使用ANSI C来编写,并且能够在不产生外部依赖(external dependencies)的情况下运行在大多数POSIX系统上,例如:Linux、*BSD、OS X和Solaris等
三、安装
1、下载&解压:
wget http://redis.googlecode.com/files/redis-3.0.0.tar.gz
tar zxvf redis-3.0.0.tar.gz
Redis可以解压至任何目录,一个make安装即可获得执行、配置文件
安装(这里将redis解压到/opt/目录下):
cd /opt/redis-3.0.0
make之后,我们会得到以下可执行文件:
redis-server:Redis服务器的daemon启动程序
redis-cli:Redis命令行操作工具。或者通过telnet进行纯文本协议操作
redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
文件位于src目录下
此外,还会得到一个默认的配置文件——redis.conf
最好,把它拷贝到固定的目录下,例如:/etc/redis/目录下
mkdir /etc/redis
cp redis.conf /etc/redis
2、运行
redis-server /etc/redis/redis.conf
3、测试
通过客户端命令redis-cli访问Redis
redis-cli
redis> set name lmt
OK
redis> get name
"lmt"
4、关闭
redis-cli shutdown
四、操作与数据结构
1、Strings
Strings是Redis中最基本的数据类型,但是别被这个名字迷惑了,因为Redis并不关心值是什么,所以你可以存放字符串、数字、十进制串等任何东西,甚至是对象的序列化。就像之前我们使用set命令把值存入键中,再通过get命令取出键对应的值一样,Redis就是这么简单。当然,与Strings相关的命令还有很多,可以到http://redis.io/查看全部的命令,这里我们就不一一介绍了。
值得强调的是Strings类型还支持位操作,如:
127.0.0.1:6379> setbit mykey 1 1
(integer) 0
127.0.0.1:6379> setbit mykey 2 1
(integer) 0
127.0.0.1:6379> setbit mykey 3 1
(integer) 0
127.0.0.1:6379> setbit mykey 10 1
(integer) 0
127.0.0.1:6379> getbit mykey 3
(integer) 1
127.0.0.1:6379> bitcount mykey
(integer) 4
setbit命令可以设置某个key指定位置为1或0,getbit可以查询key指定位置的值(0或1),bitcount命令可以查询某个key一共有多少为1的十进制位
还有一点,虽然Redis对存放的值并不关心,但有些命令却依赖于值的类型。比如incr、decr等命令,当键的值不是数值的时候就会报错:
127.0.0.1:6379> set mykey 1
OK
127.0.0.1:6379> incr mykey
(integer) 2
127.0.0.1:6379> incr mykey
(integer) 3
127.0.0.1:6379> get mykey
"3"
127.0.0.1:6379> set akey abc
OK
127.0.0.1:6379> incr akey
(error) ERR value is not an integer or out of range
2、Hash
Hash的存在使的Redis变得更加强大,功能上它类似于Java语言中的Map。对于Hash来说,一个值可以有若干个字段(field),或者叫属性,比起Strings类型使用序列化的方式来存储对象来说,使用Hash来存储对话更加合理:
127.0.0.1:6379> hset people:id001 id id001
(integer) 1
127.0.0.1:6379> hset people:id001 name ZhangSan
(integer) 1
127.0.0.1:6379> hset people:id001 age 21
(integer) 1
127.0.0.1:6379> hset people:id001 sex male
(integer) 1
127.0.0.1:6379> hget people:id001 name
"ZhangSan"
比起Strings,使用Hash来存放对象的一个好处是需要更新某个属性时,不用更新整个对象的序列化字串
3、List
List相当于编程语言中的数组,但比数组的操作要灵活很多。List类型在Redis中是有序的,使用lpush和rpush命令可以把元素分别加到数据的左边和右边,lindex命令可以获取指定位置的元素,lrange命令可以获得指定位置区间的多个元素,lpop(rpop)命令删除并返回最左边(最右边)的元素等:
127.0.0.1:6379> lpush mylist b
(integer) 1
127.0.0.1:6379> lpush mylist a
(integer) 2
127.0.0.1:6379> rpush mylist c
(integer) 3
127.0.0.1:6379> rpush mylist d
(integer) 4
127.0.0.1:6379> lindex mylist 1
"b"
127.0.0.1:6379> lrange mylist 2 3
1) "c"
2) "d"
127.0.0.1:6379> lpop mylist
"a"
127.0.0.1:6379> rpop mylist
"d"
127.0.0.1:6379> lrange mylist 0 -1
1) "b"
2) "c"
通过List,我们可以非常容易的实现各个链表、栈等数据结构,得益于Redis的优点,使用这些实现在性能上都非常的快
4、Sets
Sets是一个集合,比起List,它不允许重复的值,而且也不是有序的,所以不能通过下标索引来获取元素。可以使用sadd命令向集合中加入新的元素,smember命令返回集合中的所有元素,sismember命令判断一个元素是否属于某个集合(值得一提的是sismember命令的复杂度是O(1),不管集合中有多少个元素,它总是花费固定的时间完成执行)
127.0.0.1:6379> sadd myset java
(integer) 1
127.0.0.1:6379> sadd myset c++
(integer) 1
127.0.0.1:6379> sadd myset objective-c
(integer) 1
127.0.0.1:6379> sadd myset java
(integer) 0
127.0.0.1:6379> smembers myset
1) "objective-c"
2) "c++"
3) "java"
127.0.0.1:6379> sismember myset java
(integer) 1
127.0.0.1:6379> sismember myset c
(integer) 0
对于具体超大数据量的系统来说,使用Sets做来唯一性判断未尝不是一个好的方案
5、Sorted Sets
Sorted Sets是一个非常强大的数据结构,它在Sets的基础上,为集合中每个元素绑定了一个数值,这样一来就可以对集合做一些排序相关的操作了。zadd命令向集合中新增一个元素,同时指定该元素对应的数值;zank返回元素在集合中根据数值排序后的下标索引,zrevrank与zank类似,只是排序方式由大到小;zrange与zrevrange命令可以根据下标获取排序后的元素,非常有用的命令。 比如我们使用Sorted Sets来存放一个成绩表,可以非常容易处理诸如:多少人在90分以上,多少人不及格,80分以上的人是哪些,排名第一的是谁,多少分等等查询:
127.0.0.1:6379> zadd math:score 58 person1 63 person2 78 person3 85 person4 90 person5 100 person6
(integer) 6
127.0.0.1:6379> zrevrangebyscore math:score 100 60 //及格的人是哪些
1) "person6"
2) "person5"
3) "person4"
4) "person3"
5) "person2"
127.0.0.1:6379> zrevrangebyscore math:score 100 90 //90分以上(包括90)的人是哪些
1) "person6"
2) "person5"
127.0.0.1:6379> zrevrangebyscore math:score 100 (90 //90分以上(不包括90)的人是哪些
1) "person6"
127.0.0.1:6379> zcount math:score 90 +inf //90分以上有多少人
(integer) 2
127.0.0.1:6379> zcount math:score -inf 59 //多少人不及格
(integer) 1
127.0.0.1:6379> zrevrange math:score 0 0 withscores //排名第一的是谁,多少分
1) "person6"
2) "100"
五、主流缓存及NoSQL技术比较
Name |
HBase |
Memcached |
MongoDB |
Redis |
Solr |
|
Description |
Wide-column store based on Apache Hadoop and on concepts of BigTable |
In-memory key-value store, originally intended for caching |
One of the most popular document stores |
In-memory database with configurable options performance vs. persistency |
A widely usedenterprise search engine based onApache Lucene |
|
Developer |
Apache Software Foundation |
Danga Interactive |
MongoDB, Inc |
Salvatore Sanfilippo |
Apache Software Foundation |
|
Initial release |
2008 |
2003 |
2009 |
2009 |
2004 |
|
License |
Open Source |
Open Source |
Open Source |
Open Source |
Open Source |
|
Implementation language |
Java |
C |
C++ |
C |
Java |
|
Server operating systems |
Linux |
Linux |
Linux |
Linux |
All OS with a Java VM and a servlet container |
|
Unix |
Unix |
|||||
OS X |
OS X |
|||||
Windows |
Windows |
Windows |
Windows |
|||
|
FreeBSD |
Solaris |
BSD |
|||
Database model |
Wide column store |
Key-value store |
Document store |
Key-value store |
Search engine |
|
Data scheme |
schema-free |
schema-free |
schema-free |
schema-free |
yes |
|
Typing |
no |
no |
yes |
no |
yes |
|
Secondary indexes |
no |
no |
yes |
no |
yes |
|
SQL |
no |
no |
no |
no |
no |
|
APIs and other access methods |
Java API |
Proprietary protocol |
proprietary protocol using JSON |
proprietary protocol |
Java API |
|
RESTful HTTP API |
RESTful HTTP API |
|||||
Thrift |
|
|||||
Supported programming languages |
C |
C |
C |
C |
||
C# |
.Net |
C# |
C# |
.Net |
||
C++ |
C++ |
C++ |
C++ |
|||
Groovy |
ColdFusion |
Groovy |
Clojure |
|||
Java |
Java |
Java |
Java |
Java |
||
Erlang |
Erlang |
Erlang |
Erlang |
|||
Python |
Python |
Python |
Python |
Python |
||
Scala |
Lua |
Scala |
Scala |
Scala |
||
|
Ruby |
Ruby |
Ruby |
Ruby |
||
PHP |
PHP |
PHP |
PHP |
PHP |
||
|
JavaScript |
JavaScript |
JavaScript |
|||
|
Perl |
Perl |
Perl |
Perl |
||
|
OCaml |
Lua |
Lua |
any language that supports sockets and either XML or JSON |
||
|
Lisp |
Lisp |
Lisp |
|
||
|
|
Dart |
Dart |
|
||
|
|
ColdFusion |
|
|
||
|
|
Go |
Go |
|
||
|
|
Actionscript |
Objective-C |
|
||
|
|
Haskell |
Haskell |
|
||
|
|
Smalltalk |
Smalltalk |
|
||
|
|
Clojure |
Tcl |
|
||
|
|
MatLab |
|
|
||
|
|
PowerShell |
|
|
||
|
|
Prolog |
|
|
||
Server-side scripts |
yes |
no |
JavaScript |
Lua |
Java plugins |
|
Triggers |
yes |
no |
no |
no |
no |
|
Partitioning methods |
Sharding |
none |
Sharding |
none |
Sharding |
|
Replication methods |
selectable replication factor |
none |
Master-slave replication |
Master-slave replication |
cloud/distributed (via Zookeeper) |
|
Master-slave replication |
||||||
MapReduce |
yes |
no |
yes |
no |
no |
|
Consistency concepts |
Immediate Consistency |
|
Eventual Consistency |
|
Eventual Consistency |
|
Immediate Consistency |
||||||
Foreign keys |
no |
no |
no |
no |
no |
|
Transaction concepts |
no |
no |
no |
optimistic locking |
optimistic locking |
|
Concurrency |
yes |
yes |
yes |
yes |
yes |
|
Durability |
yes |
no |
yes |
yes |
yes |
|
User concepts |
Access Control Lists (ACL) |
yes |
Users can be defined with full access or read-only access |
very simple password-based access control |
|
|
Specific characteristics |
|
|
|
Redis very much emphasize performance. In any design decisions performance has priority over features or memory requirements. |
Architecture: Lives in web stack, ships by default with Jetty. Connectors, JDBC, multiple languages, true morphological CJK, binary document filters (Tika), Entity Extraction (UIMA) |
|
Typical application scenarios |
|
Mostly used for caching |
|
Applications that can hold all data in memory, and that have high performance requirements. |
|