Redis入门

1. Redis简介

随着互联网尤其是Web2.0技术的迅猛发展,每个网民都成为信息发布者和消费者。Web服务器中的数据存储量呈爆炸增长趋势,而单位时间内Web服务器接收的访问请求也在逐步增加。这对后台数据库处理大规模数据和应对高并发访问的能力,提出越来越高的要求。传统的关系数据库由于其固有缺陷难以有效支持新型Web应用。

NoSQL数据库作为一类新型非关系数据库,具有高性能、高效存储、高可用性和高可扩展性等诸多优势。它结构简单,读写效率高,支持服务器集群,能够处理海量数据,可以应对高并发访问。NoSQL数据库打破了关系数据库的垄断局面,被广泛应用于各种大型Web应用。目前,NoSQL数据库有大量商业实现,如:Google的BigTable,Amazon的Dynamo 等等。除此之外,NoSQL数据库也有一些开源实现,如:Redis,Memcached,HBase等等。

Redis是一种开源的基于Key-Value的轻量级NoSQL数据库。该项目使用BSD授权协议,由Salvatore Sanfilippo于2009年发起,最新的稳定版本为2.4.0。Redis用C语言编写而成,源代码仅4万行左右,编译后二进制文件不到1M,能够方便地嵌入到各种应用环境。麻雀虽小,五脏俱全。Redis除支持基本的针对Key-Value的Get/Set操作外,还具备若干实用的新特性。

Redis中的Value不仅能够存储String类型,还能存储List,Set,Sorted Set和Hash四种常见的数据结构,并提供针对这些数据结构的操作原语,这为开发人员提供了极大便利,能够有效减少网络数据传输量。Redis也被称为“数据结构服务器”。

Redis支持Master/Slave集群。集群中有一台Master服务器,其下可以挂载若干Slave服务器,而Slave服务器下还可挂载若干Slave服务器,每个Slave服务器都是Master服务器的镜像。读操作可以负载均衡到各个服务器上并行执行。写操作则先阻塞各Slave服务器,然后在Master服务器上执行,最后把修改传播到各Slave服务器并解除阻塞。

Redis支持内存数据持久化。它能够把内存中存储的数据按照一定策略写入硬盘文件,并通过读取硬盘文件重建内存数据。这能够在一定程度上缓解服务器崩溃导致的数据丢失问题。Redis支持Snapshotting和AOF两种持久化方法:前者能够导出完整镜像文件,相当于完全备份;后者则在日志文件中记录每个写操作,相当于增量备份。

Redis实现了独立于操作系统的Virtual Memory管理系统,能优化系统运行效率。Redis还支持Pipelining批处理,能提高系统吞吐量。

Redis的诸多优点吸引了大批开发人员,它被广泛地应用于各种NoSQL数据库适用的场合,譬如程序员问答社区StackOverFlow就使用Redis作为缓存服务器。

下面将详细介绍Redis的安装和使用方法。

2. Redis安装配置

a) Redis安装

Redis目前最新的稳定版本是2.4.0。可以访问redis.io获得Redis源代码包,然后运行如下命令进行安装:

>cd /opt/

>cp ($DOWNLOAD_DIR)/redis-2.4.0.tar.gz ./

>tar -xvf redis-2.4.0.tar.gz

>cd redis-2.4.0/

>make

>make test

>make install

运行如下命令开启Redis Server:

>redis-server

运行如下命令开启Redis Client:

>redis-cli

b) Redis配置

Redis Server启动时使用默认配置,也可运行如下命令使用自定义配置文件:

>redis-server ($CONF_PATH)/(CONF_FILE)

下面介绍Redis Server的常用配置选项:

bind <IP Address>

设置Redis Server绑定的IP。默认为127.0.0.1。

port <Port Number>

设置Redis Server绑定的端口。默认为6379。

slaveof <Master IP> <Master Port>

设置Redis Server为Slave服务器,从属于参数指定的服务器(Master或Slave)。默认为Master服务器。

save <Second> <Change>

设置Snapshotting持久化策略,如果在Second秒时间内,有不少于Change个写操作,则将内存数据同步到硬盘。默认关闭Snapshotting持久化。

appendonly <yes|no>

设置AOF持久化策略,将每个写操作记录在日志文件中。默认关闭AOF持久化。

appendfsync <always|everysec|no>

设置AOF持久化策略的同步方式,always表示每执行一个写操作即写入日志文件,everysec表示每隔一秒将累积的写操作写入日志文件,no表示由操作系统决定何时将累积的写操作写入日志文件。默认为no。

maxclients <Number>

设置最大连接数为Number。默认为无限制。

maxmemory <Byte>

设置最大内存占用为Byte个字节。默认为无限制。

3. Redis常用命令

Redis提供了基于命令行的Client工具,运行如下命令连接到默认的Server(127.0.0.1:6379):

>redis-cli

也可使用如下命令连接到指定的Server:

>redis-cli -h <IP Address> -p <Port Number>

下面按数据类型分类介绍Redis的常用命令:

a) String类命令

>SET StrKey StrValue //设置StrKey对应的String值为StrValue

OK

>GET StrKey //查询StrKey对应的String值

"StrValue"

>APPEND StrKey BlaBla //将BlaBla追加到StrKey对应的String值

(integer) 14

>GET StrKey //查询StrKey对应的String值

"StrValueBlaBla"

>SET AnotherStrKey 9 //设置AnotherStrKey对应的String值为9

OK

>INCR AnotherStrKey //将AnotherStrKey对应的String值加1

(integer 1)

>GET AnotherStrKey //查询AnotherStrKey对应的String值

"10"

b) List类命令

>LPUSH ListKey A //在ListKey对应的List左侧插入A

(integer 1)

>LPUSH ListKey B //在ListKey对应的List左侧插入B

(integer 2)

>RPUSH ListKey C //在ListKey对应的List右侧插入C

(integer 3)

>RPUSH ListKey D //在ListKey对应的List右侧插入D

(integer 4)

>LRANGE ListKey 0 3 //查询ListKey对应的List的0~3位的值

1) "B"

2) "A"

3) "C"

4) "D"

>LPOP ListKey //在ListKey对应的List左侧删除值

"B"

>LRANGE ListKey 0 2 //查询ListKey对应的List的0~2位的值

1) "A"

2) "C"

3) "D"

>RPOP ListKey //在ListKey对应的List右侧删除值

"D"

>LRANGE ListKey 0 1 //查询ListKey对应的List的0~1位的值

1) "A"

2) "C"

c) Set类命令

>SADD SetKey 1 //在SetKey对应的Set中插入1

(integer 1)

>SADD SetKey 2 //在SetKey对应的Set中插入2

(integer 1)

>SMEMBERS SetKey //查询SetKey对应的Set中的所有值

1) "1"

2) "2"

>SADD AnotherSetKey 1 //在AnotherSetKey对应的Set中插入1

(integer 1)

>SADD AnotherSetKey 3 //在AnotherSetKey对应的Set中插入3

(integer 1)

>SMEMBERS AnotherSetKey //查询AnotherSetKey对应的Set中的所有值

1) "1"

2) "3"

>SDIFF SetKey AnotherSetKey //计算SetKey和AnotherSetKey的差集

1) "2"

>SINTER SetKey AnotherSetKey //计算SetKey和AnotherSetKey的交集

1) "1"

>SUNION SetKey AnotherSetKey //计算SetKey和AnotherSetKey的并集

1) "1"

2) "2"

3) "3"

d) SortedSet类命令

>ZADD SSKey 4 Fourth //在SSKey中插入Fourth,优先级为4

(integer 1)

>ZADD SSKey 3 Third //在SSKey中插入Third,优先级为3

(integer 1)

>ZADD SSKey 2 Second //在SSKey中插入Second,优先级为2

(integer 1)

>ZADD SSKey 1 First //在SSKey中插入First,优先级为1

(integer 1)

>ZRANGE SSKey 0 3 //查询SSKey的0~3位的值

1) "First"

2) "Second"

3) "Third"

4) "Fourth"

e) Hash类命令

>HSET HashKey ID 1 //设置HashKey中字段ID的值为1

(integer 1)

>HSET HashKey Name Jack //设置HashKey中字段Name的值为Jack

(integer 1)

>HSET HashKey Age 25 //设置HashKey中字段Age的值为25

(integer 1)

>HGET HashKey Name //查询HashKey中字段Name的值

"Jack"

>HGETALL HashKey //查询HashKey中的所有字段及其对应的值

1) "ID"

2) "1"

3) "Name"

4) "Jack"

5) "Age"

6) "25"

4. Redis Client API

由于Redis使用的协议比较简单,已经开发出大量的Redis Client API库,支持几乎所有的主流开发语言,如:hiredis(C),ServiceStack.Redis(C#),Jedis(Java),Predis(PHP),redis-py(Python),redis-rb(Ruby)等等。事实上,Redis自带的Client工具redis-cli就是利用hiredis写成。下面将用一个完整的示例程序简要介绍hiredis的使用:

#include "hiredis.h"

#include <stdio.h>

#include <stdlib.h>

int main()

{

int i;

redisContext *context = NULL;

redisReply *reply = NULL;

char *ipStr = "192.168.1.1";

unsigned int portNum = 6379;

//Connect to redis server

context = redisConnect(ipStr, portNum);

if(context->err)

{

printf("Connection Failed!\n");

exit(1);

}

//Execute "SET a aaa"

reply = redisCommand(context, "SET %s %s", "a", "aaa");

freeReplyObject(reply);

//Execute "GET a"

reply = redisCommand(context, "GET %s", "a");

printf("\"%s\"\n", reply->str);

freeReplyObject(reply);

//Execute "LPUSH b 1", "LPUSH b 2" and "LPUSH b 3"

for(i=1 ; i<=3 ; i++)

{

reply = redisCommand(context, "LPUSH %s %d", "b", i);

freeReplyObject(reply);

}

//Execute "LRANGE b 0 2"

reply = redisCommand(context, "LRANGE %s %d %d", "b", 0, 2);

for(i=0 ; i<reply->elements ; i++)

printf("%d) \"%s\"\n", i+1, reply->element[i]->str);

freeReplyObject(reply);

return 0;

}

该程序首先调用redisConnect函数,创建一个到192.168.1.1:6379的Redis Server的连接。这个函数的第一个参数是服务器的IP地址,第二个参数是服务器的端口号。连接的上下文信息保存在context指针指向的redisContext结构体中,如果连接失败则打印提示信息并退出。

然后调用redisCommand函数,执行各种Redis命令。这个函数的第一个参数是一个指向redisContext结构体的指针,第二个参数是表示Redis命令的字符串模板,最后是变长参数列表用来表示模板中的填充值。Redis命令的执行结果保存在reply指针指向的redisReply结构体中。

接着分析redisReply结构体中保存的信息。通常Redis命令可以有一个或者多个返回值。当只有一个返回值时,信息存储在str字段中,这是一个字符指针;当有多个返回值时,返回值的数目存储在elements字段中,而具体信息存储在element字段中,这是一个指向redisReply结构体指针的指针,element[i]为指向第i个返回值对应的redisReply结构体的指针。

最后调用freeReplyObject函数,释放reply指针指向的redisReply结构体以及该结构体下属的内存资源,防止出现内存泄露的情况。

编译并运行这段程序,得到如下输出:

"aaa"

1) "3"

2) "2"

3) "1"

5. 总结

本文首先分析了NoSQL数据库相对于传统的关系数据库的优势,介绍了一种开源的基于Key-Value的轻量级NoSQL数据库Redis的概况,列举了Redis的各种实用特性:支持大量的数据类型及其操作,支持Master/Slave架构的集群,支持内存数据持久化。然后描述了Redis安装和配置的详细步骤,包括:源代码的下载和编译;服务器的常规配置、集群配置和持久化配置。接着分门别类地介绍针对String,List,Set,SortedSet和Hash类型的Redis常用命令。最后介绍Redis Client API,并用一个示例程序详细讲解C语言库hiredis的使用。

至此,我们已经学会了Redis的入门知识。如果您对Redis感兴趣,希望进行更加深入的了解,您可以访问下列资源或者利用搜索引擎获取相关信息。您也可以在自己的项目中使用Redis,通过实战更好地掌握Redis。此外,由于Redis是一个高速发展中的开源项目,您还可以建议Redis作者开发新特性甚至贡献自己的代码。

您还在等什么呢?

赶快来开发自己的Redis应用吧!!!

参考资料

http://redis.io

Redis官方网站

http://redis.io/commands

Redis命令手册

http://redis.io/clients

Redis Client API列表。列出了各种语言的开发库以及相应的下载地址。

http://try.redis-db.com/

Redis在线教程。它提供基于Web的Redis体验,使您无需安装即可使用Redis。您可以跟着教程逐步熟悉各种Redis命令。

作者简介

刘华晖,IBM CSTL 软件工程师,liuhhsh@cn.ibm.com。

注:

本文“黑色”部分为正文或注释,“绿色”部分为输入(命令、配置或源代码),“蓝色”部分为输出(命令或程序的执行结果)。

发表评论