介绍
Redis
是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
版本
官方版本
目前官方版本支持Linux
系统和Ubuntu
系统。官方下载地址:http://redis.io/download
由于我们的开发项目以Windows为主,所以在此不对官方版本做详细介绍,有兴趣的可以到官网查看。
非官方版本(Windows 版本)
官方没有Redis
的Windows版本,但是微软开源技术团队(Microsoft Open Tech group)自行开发和维护了一个 Win64 的版本。
- 微软团队只提供了官方64位版本,而32位版本,需要自己从源代码构建。
- Released版本中提供了msi文件,Redis
可以作为Windows服务安装
安装服务
- 下载Win64的压缩文件到一个指定文件夹
- 打开一个 cmd 窗口 使用cd命令切换目录到解压缩的文件夹下运行
redis-server.exe redis.windows.conf
redis-server.exe
启动Redis服务redis.windows.conf
Redis服务的一些配置,不写则会调用默认设置- 端口号默认
6379
可以通过修改配置文件redis.windows-service.conf
修改或CONFIG set
命令修改
运行客户端
- 打开一个 cmd 窗口 使用cd命令切换目录到解压缩的文件夹运行
redis-cli.exe -h 127.0.0.1 -p 6379
redis-cli.exe
启动Redis客户端-h 127.0.0.1
服务器IP地址-p 6379
服务器端口号
优点
- 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
- 支持丰富数据类型,支持string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
- 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
- 丰富的特性,可用于缓存,消息,按key设置过期时间,过期后将会自动删除
缺点
- redis存储成本高(纯使用内存,单台机器,存储的数据量,跟机器本身的内存大小有关),所以不能当做海量数据库来用。虽然redis本身有key过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据。
- 如果进行完整重同步,由于需要生成rdb文件,并进行传输,会占用主机的CPU,并会消耗现网的带宽。不过redis2.8版本,已经有部分重同步的功能,但是还是有可能有完整重同步。比如,新上线的备机。
- 修改配置文件,进行重启,将硬盘中的数据加载进内存,时间比较久。在这个过程中,redis不能提供服务。
适合应用场景
redis是一种k/v的内存数据库,适合小数据量的存储以及实时要求高的地方,用来存储一些需要频繁调取的数据,这样可以大大节省系统直接读取磁盘来获得数据的I/O开销,更重要的是可以极大提升速度,但是不适合做完整数据库,完整数据库基本上都有一套详细解决方案。
Java 使用 Redis
安装
- 安装 Redis 服务
- 配置 Java 运行环境,确保能正常使用Java
- 安装 Java Redis 驱动
jedis.jar
连接到 redis 服务
import redis.clients.jedis.Jedis;
public class RedisJava {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println("连接成功");
//查看服务是否运行
System.out.println("服务正在运行: "+jedis.ping());
}
}
存取String类型的数据
import redis.clients.jedis.Jedis;
public class RedisStringJava {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println("连接成功");
//设置 redis 字符串数据
jedis.set("runoobkey", "www.runoob.com");
// 获取存储的数据并输出
System.out.println("redis 存储的字符串为: "+ jedis.get("runoobkey"));
}
}
编译结果:
连接成功
redis 存储的字符串为: www.runoob.com
存取List类型的数据
import java.util.List;
import redis.clients.jedis.Jedis;
public class RedisListJava {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println("连接成功");
//存储数据到列表中
jedis.lpush("site-list", "Runoob");
jedis.lpush("site-list", "Google");
jedis.lpush("site-list", "Taobao");
// 获取存储的数据并输出
List<String> list = jedis.lrange("site-list", 0 ,2);
for(int i=0; i<list.size(); i++) {
System.out.println("列表项为: "+list.get(i));
}
}
}
编译结果:
连接成功
列表项为: Taobao
列表项为: Google
列表项为: Runoob
存取的Keys
import java.util.Iterator;
import java.util.Set;
import redis.clients.jedis.Jedis;
public class RedisKeyJava {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println("连接成功");
// 获取数据并输出
Set<String> keys = jedis.keys("*");
Iterator<String> it=keys.iterator() ;
while(it.hasNext()){
String key = it.next();
System.out.println(key);
}
}
}
编译结果:
连接成功
runoobkey
site-list
Redis发布与订阅
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
订阅频道
通过SUBSCRIBE
命令客户端可以订阅指定的频道,当这个频道有其他客户端推送的消息时,当前客户端就会收到。
例:订阅first和second频道
SUBSCRIBE first second
消息推送
通过PUBLISH
命令客户端可以向指定频道推送消息,订阅这个频道的客户端都会收到一条message类型的消息。
例:推送消息”Hello”到first频道
PUBLISH first "Hello"
退订频道
通过UNSUBSCRIBE
命令客户端可以推定指定频道。如果没有频道被指定,即一个无参数的 UNSUBSCRIBE 调用被执行,那么客户端使用SUBSCRIBE
命令订阅的所有频道都会被退订。在这种情况下,命令会返回一个信息,告知客户端所有被退订的频道。
例:退订second频道
UNSUBSCRIBE second
模式匹配
Redis
的Pub/Sub实现支持模式匹配。客户端可以订阅全风格的模式以便接收所有来自能匹配到给定模式的频道的消息。
- 模式匹配订阅命令PSUBSCRIBE
- 模式匹配退订命令UNPSUBSCRIBE
- 接收消息为pmessage类型
SUBSCRIBE first
PSUBSCRIBE f*
PSUBSCRIBE news.*
注意:如果它订阅的多个模式匹配了同一个发布的消息,客户端可能多次接收一个消息。
JAVA实现Redis消息推送
- 创建一个频道的监听类继承Redis的抽象类
JedisPubSub
,并实现其抽象方法。订阅频道,取消订阅,收到消息等状态会对应调用相关的方法。 - 订阅频道
public class TestSubscribe {
public static void main(String[] args) {
//连接本地的 Redis 服务
Jedis jedis = new Jedis("localhost");
System.out.println("连接成功");
// 创建频道监听对象
RedisMsgPubSubListener listener = new RedisMsgPubSubListener();
// 订阅频道,绑定监听
jedis.subscribe(listener, "redisChatTest");
}
}
注意:subscribe
是一个阻塞的方法,在取消订阅该频道前,会一直阻塞在这,只有当取消了订阅才会执行之后的代码。
- 发送消息
Public class TestPublish {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost");
jedis.publish("redisChatTest", "Hello");
Thread.sleep(5000);
jedis.publish("redisChatTest", "Redis");
Thread.sleep(5000);
jedis.publish("redisChatTest", "Message publish");
}
}
- 退订频道
import redis.clients.jedis.JedisPubSub;
public class RedisMsgPubSubListener extends JedisPubSub {
...
@Override
public void onMessage(String channel, String message) {
System.out.println("channel:" + channel + "receives message :" + message);
// 退订
this.unsubscribe();
}
...
}
参考:
http://www.redis.cn/documentation.html
http://blog.csdn.net/u013322876/article/details/53817757
http://blog.csdn.net/canot/article/details/51938955