一、简介
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,是一种非关系型数据库(nosql)。
Redis和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
redis使用了两种文件格式:全量数据(全量数据格式是把内存中的数据写入磁盘,便于下次读取文件进行加载)和增量请求(增量请求文件则是把内存中的数据序列化为操作请求,用于读取文件进行replay得到数据,序列化的操作包括SET、RPUSH、SADD、ZADD)。
二、安装
Redis win版本下载地址 下载完解压后进入在cmd中进入redis的安装目录,并输入redis-server.exe redis.windows.conf创建临时redis服务器。
修改Redis服务的密码可以在redis.windows.conf或redis.windows-service.conf中修改 requirepass 后面的参数即可。
三、搭建
1.依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${redis.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring.redis.version}</version>
</dependency>
2.redis.properties
配置信息
redis.host=127.0.0.1
redis.port=6379
redis.timeout=3
redis.password=root
redis.poolMaxTotal=10
redis.poolMaxldle=10
redis.poolMaxWait=3
3.service
实现Redis服务
package com.imooc.miaosha.redis;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@Service
public class RedisService {
@Autowired
JedisPool jedisPool;
/*获取当个对象*/
public <T> T get(KeyPrefix prefix,String key,Class<T> clazz){
Jedis jedis=null;
try {
jedis=jedisPool.getResource();
//生成真正的key
String realKey=prefix.getPrefix()+key;
String str=jedis.get(realKey);
T t=stringToBean(str,clazz);
return t;
}finally {
returnToPool(jedis);
}
}
/*设置对象*/
public <T> boolean set(KeyPrefix prefix,String key,T value){
Jedis jedis=null;
try {
jedis=jedisPool.getResource();
String str=stringToBean(value);
if(str==null||str.length()<=0){
return false;
}
//
String realKey=prefix.getPrefix()+key;
int seconds=prefix.expireSecconds();
if (seconds<=0){
jedis.set(realKey,str);
}else{
jedis.setex(realKey,seconds,str);
}
return true;
}finally {
returnToPool(jedis);
}
}
private <T>String stringToBean(T value){
if(value==null){
return null;
}
Class<?> clazz=value.getClass();
if(clazz==int.class||clazz==Integer.class){
return " "+value;
}else if(clazz==String.class){
return (String)value;
}else if(clazz==long.class||clazz==Long.class){
return " "+value;
}else{
return JSON.toJSONString(value);
}
}
private void returnToPool(Jedis jedis){
if(jedis!=null){
jedis.close();
}
}
private <T> T stringToBean(String str,Class<T> clazz){
if(str==null||str.length()<=0||clazz==null){
return null;
}
if(clazz==int.class||clazz==Integer.class){
return (T)Integer.valueOf(str);
}else if(clazz==String.class){
return (T)str;
}else if(clazz==long.class||clazz==Long.class){
return (T)Long.valueOf(str);
}else{
return JSON.toJavaObject(JSON.parseObject(str),clazz);
}
}
/*判断key是否存在*/
public <T> boolean exists(KeyPrefix prefix,String key){
Jedis jedis=null;
try {
jedis=jedisPool.getResource();
//生成真正的key
String realKey=prefix.getPrefix()+key;
return jedis.exists(realKey);
}finally {
returnToPool(jedis);
}
}
public <T> Long incr(KeyPrefix prefix,String key){
Jedis jedis=null;
try {
jedis=jedisPool.getResource();
//生成真正的key
String realKey=prefix.getPrefix()+key;
return jedis.incr(realKey);
}finally {
returnToPool(jedis);
}
}
public <T> Long decr(KeyPrefix prefix,String key){
Jedis jedis=null;
try {
jedis=jedisPool.getResource();
//生成真正的key
String realKey=prefix.getPrefix()+key;
return jedis.decr(realKey);
}finally {
returnToPool(jedis);
}
}
}
4.RedisPool
获取Redis对象,用@Bean将JedisPool注入Spring容器。
package com.imooc.miaosha.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Service
public class RedisPoolFactory {
@Autowired
RedisConfig redisConfig;
@Bean
public JedisPool JedisPoolFactory(){
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(redisConfig.getPoolMaxldle());
poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait()* 1000);
JedisPool jp = new JedisPool(poolConfig, redisConfig.getHost(), redisConfig.getPort(),redisConfig.getTimeout()*1000
,redisConfig.getPassword(),0);
return jp;
}
}
5.RedisConfig
建立成员变量接受配置的对应数据信息。
package com.imooc.miaosha.redis;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "redis")
public class RedisConfig {
private String host;
private int port;
private int timeout;
private String password;
private int poolMaxTotal;
private int poolMaxldle;
private int poolMaxWait;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPoolMaxTotal() {
return poolMaxTotal;
}
public void setPoolMaxTotal(int poolMaxTotal) {
this.poolMaxTotal = poolMaxTotal;
}
public int getPoolMaxldle() {
return poolMaxldle;
}
public void setPoolMaxldle(int poolMaxldle) {
this.poolMaxldle = poolMaxldle;
}
public int getPoolMaxWait() {
return poolMaxWait;
}
public void setPoolMaxWait(int poolMaxWait) {
this.poolMaxWait = poolMaxWait;
}
}
6.Prefix
通过KeyPrefix 区分模块,对keyj进行封装,避免key被覆盖,采用方式是:接口->抽象类->实现类。
package com.imooc.miaosha.redis;
public interface KeyPrefix {
public int expireSecconds();
public String getPrefix();
}
package com.imooc.miaosha.redis;
public abstract class BasePrefix implements KeyPrefix{
private int expireSeconds;
private String prefix;
public BasePrefix(String prefix) {//0代表永不过期
this(0,prefix);
}
public BasePrefix(int expireSeconds, String prefix) {
this.expireSeconds = expireSeconds;
this.prefix = prefix;
}
@Override
public int expireSecconds() {
return expireSeconds;
}
@Override
public String getPrefix() {
String className=getClass().getSimpleName();
return className+":"+prefix;
}
}