一、pom文件
新建spring boot项目,下面给大家看pom.xml文件的配置
<groupId>study</groupId>
<artifactId>redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>redis</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<geotools.version>19.2</geotools.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Spring boot热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- servlet依赖. -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!--json-lib -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
二、配置文件
配置完pom文件后,配置resource.properties文件,文件配置如下:
server.port=8081
server.context-path=/redisStudy
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=0
三、代码结构
配置完成之后,就可以编写代码了,也是spring boot项目的快捷的地方,首先看看我的目录结构,为了方便我把所有的类都写在一个文件夹下面了
五、具体代码
下面给大家看每个文件的代码:
A.app.java:主要就是启动作用:
package study.redis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Hello world!
*
*/
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
B。RedisConfig.java redis的一些配置,代码如下
package study.redis;
import java.lang.reflect.Method;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis加载
* @author 17444
*
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
@Bean
public CacheManager CacheManagercacheManager(RedisTemplate<?, ?> redisTemplate) {
CacheManager cacheManager = new RedisCacheManager(redisTemplate);
return cacheManager;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(factory);
// 修改rdis默认序列化方式为StringRedisSerializer
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(stringRedisSerializer);
return redisTemplate;
}
}
C.RdisTemplateUtils.java 封装的一些redisTemplate的基本操作,代码如下:
package study.redis;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
/**
* RedisTemplate操作工具类
*
* @author 17444
*
*/
@Component
public class RdisTemplateUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 制定緩存失效時間
*
* @param key
* @param time
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key获取过期时间
*
* @param key
* @return
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key);
}
/**
* 判断key是否存在
*
* @param key
* @return
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key
*/
@SuppressWarnings("unchecked")
public void delKey(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
// ---------------------------对String的操作-------------------------------------------------
/**
* 模糊查询
*
* @param key
* @return
*/
public Set<String> getKeys(String key) {
return redisTemplate.keys(key);
}
/**
* 获取缓存
*
* @param key
* @return
*/
public Object getCash(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存多个获取
*
* @Title: mGet
* @param key List类型的多个键
* @return Object 值
*/
public Object mGet(List<String> keys) {
if (null == keys || 0 == keys.size()) {
return null;
}
return redisTemplate.opsForValue().multiGet(keys);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存多个放入
*
* @param @param map 多个键值对
* @return true成功 false 失败
*/
public boolean mSet(Map<String, Object> map) {
try {
redisTemplate.opsForValue().multiSet(map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// ================================Map=================================
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 设置缓存
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
// ============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0)
expire(key, time);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
// ===============================list=================================
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0)
expire(key, time);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
D.SerializationUtil.java 自定义的序列化工具类,为后面存储自定义的对象做准备
package study.redis;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.springframework.stereotype.Component;
@Component
public class SerializationUtil {
public SerializationUtil() {
// TODO Auto-generated constructor stub
}
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
}
return null;
}
/**
* 反序列化
*
* @param bytes
* @return
*/
public static Object deserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
}
return null;
}
}
E:User 实体类,自定义的对象,
package study.redis;
import java.io.Serializable;
public class User implements Serializable{
public static final String OBJECT_KEY = "USER";
/**
*
*/
private static final long serialVersionUID = 1L;
private String id;
private String name;
private int age;
private String sex;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public User() {
super();
}
public User(String id, String name, int age, String sex) {
super();
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
public Object getKey() {
return OBJECT_KEY;
}
public String getObjectKey() {
return getId();
}
}
F。UserService.java 调用序列化工具,存储自定的user对象到redis数据库中的接口
package study.redis;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public UserService() {
}
@Autowired
RedisTemplate<String, Object> redisTemplate;
@Resource
SerializationUtil serializationUtil;
public RedisTemplate<String, Object> getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@SuppressWarnings("static-access")
public void put(User user) {
redisTemplate.opsForHash().put(user.getObjectKey(), user.getKey(),serializationUtil.serialize(user) );
}
public void delete(User key) {
redisTemplate.opsForHash().delete(key.getObjectKey(), key.getKey());
}
@SuppressWarnings("static-access")
public User get(User key) {
return (User)serializationUtil.deserialize( (byte[]) redisTemplate.opsForHash().get(key.getObjectKey(), key.getKey()));
}
}
G。DemoController:主要就是各种实际的业务对redis'数据存储等操作:
package study.redis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import net.sf.json.JSONObject;
@Controller
@RequestMapping(value = "/demo")
public class DemoColler {
@Resource
private RdisTemplateUtils rdisTemplateUtils;
@Autowired
RedisTemplate<String, Object> redisTemplate;
@Resource
private UserService userService;
@Resource
SerializationUtil serializationUtil;
@RequestMapping(value = "/demo1")
@ResponseBody
public Map<Object, Object> demo1() {
//String的基本操作
// 存入String类型到数据库
rdisTemplateUtils.set("helloWord", "yyyhbhjbhjhh is fristTry");
// //获取String类型到数据
System.out.println(rdisTemplateUtils.getCash("helloWord"));
//map的基本操作
Map<String,Object> testMap = new HashMap<String,Object>();
testMap.put("1", "testMapValue1");
testMap.put("2", "testMapValue2");
testMap.put("3", "testMapValue3");
//存储成map的数据格式
rdisTemplateUtils.hmset("testMap", testMap);
//获取数据
Map<Object, Object> testMapReturn = rdisTemplateUtils.hmget("testMap");
System.out.println(testMapReturn);
System.out.println(rdisTemplateUtils.hget("testMap", "2"));
rdisTemplateUtils.hset("testMap","4","testMapValue444");
rdisTemplateUtils.hdel("testMap", "2");
System.out.println(rdisTemplateUtils.hHasKey("testMap", "2"));
//set的基本操作
rdisTemplateUtils.sSet("testall","testSet3","testSet4");
rdisTemplateUtils.sSet("StrinSet","Stringset1","Stringset12");
Set<Object> setResukt = rdisTemplateUtils.sGet("testSet1");
rdisTemplateUtils.setRemove("testall", "testSet3");
System.out.println(setResukt);
rdisTemplateUtils.sSet("strarrays545", "hjihjihjk","djhdsjhaj");
//list的基本操作
rdisTemplateUtils.lSet("list1", "35");
rdisTemplateUtils.lSet("list1", "38");
List<Object> tstList = new ArrayList<Object>();
tstList.add("aaa");
tstList.add("bb");
rdisTemplateUtils.lSet("testList", tstList);
System.out.println(rdisTemplateUtils.lGetIndex("testList", 1));
System.out.println(rdisTemplateUtils.lGet("list1", 1,3));
rdisTemplateUtils.lUpdateIndex("list1", 1,"hh");
return null;
}
//存储自定义对象,将redistemplate的序列化方式变成如下:
/**
* StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jdkSerializationRedisSerializer);
redisTemplate.setValueSerializer(jdkSerializationRedisSerializer);
* @return
*/
@RequestMapping(value = "/demo2")
@ResponseBody
public Map<Object, Object> demo2() {
User user1 = new User(UUID.randomUUID().toString(), "jack4", 24, "m");
User user2 = new User(UUID.randomUUID().toString(), "jack5", 25, "m");
System.out.println("==== getting objects from redis ====");
System.out.println("User is not in redis yet: " + userService.get(user1));
System.out.println("User is not in redis yet: " + userService.get(user2));
System.out.println("==== putting objects into redis ====");
userService.put(user1);
userService.put(user2);
System.out.println("==== getting objects from redis ====");
System.out.println("User should be in redis yet: " + userService.get(user1));
User user = userService.get(user1);
System.out.println(user.getName());
System.out.println("User should be in redis yet: " + userService.get(user2));
System.out.println("==== deleting objects from redis ====");
userService.delete(user1);
userService.delete(user2);
System.out.println("==== getting objects from redis ====");
System.out.println("User is not in redis yet: " + userService.get(user1));
System.out.println("User is not in redis yet: " + userService.get(user2));
return null;
}
//存储自定义对象,将redistemplate的序列化方式变成如下:
/**
* StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(stringRedisSerializer);
* @return
*/
@RequestMapping(value = "/demo3")
@ResponseBody
public Map<Object, Object> demo3() {
User u1 = new User(UUID.randomUUID().toString(),"jack1",21,"m");
JSONObject u1J = JSONObject.fromObject(u1);
rdisTemplateUtils.set("ndjahjd", u1J.toString());
String value = (String) rdisTemplateUtils.getCash("ndjahjd");
JSONObject jsonObject=JSONObject.fromObject(value);
User stu=(User)JSONObject.toBean(jsonObject, User.class);
int agee = stu.getAge();
return null;
}
}
六、总结
以上的代码,就基本完成了redis的一些基础学习
在保存自定义对象的时候,我们可以看到,我们是用了两种方式去保存的,其中不同的方式引用了不同的序列化方式,
下面我们简单介绍下redis的序列化方式,由于resis没有规定自己配套使用的序列化方式,所以我们从spring-data-redis序列化方式里面选择,
spring-data-redis默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。
StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。StringRedisSerializer
RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的JdkSerializationRedisSerializer
1、spring-data-redis的序列化类
spring-data-redis的序列化类有下面这几个:
GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
JacksonJsonRedisSerializer: 序列化object对象为json字符串
JdkSerializationRedisSerializer: 序列化java对象(被序列化的对象必须实现Serializable接口),无法转义成对象
StringRedisSerializer: 简单的字符串序列化
GenericToStringSerializer:类似StringRedisSerializer的字符串序列化
GenericJackson2JsonRedisSerializer:类似Jackson2JsonRedisSerializer,但使用时构造函数不用特定的类参考以上序列化,自定义序列化类;
Jdk序列化速度快,占用空间大,不易查看,通过redis命令查看类似\xAC\xED\x00\x05t\x00\x011不方便
Hash最好还是用GenericJackson2JsonRedisSerializer
推荐将所有Template的key都采用String的序列化方式,而value的序列化方式可以采用不同的序列化方式。(jreids自动选择)(这样还有一个好处就是不必string的也采用jdk的序列化从而导常用数据格式致为了存储数据结构浪费空间)
2、Redis目前支持5种数据类型
Redis目前支持5种数据类型,分别是:
- String(字符串)
- List(列表)
- Hash(字典)
- Set(集合)
- Sorted Set(有序集合)
3、redis不同的数据类型使用场景
下面介绍下。五种类型的使用场景
a. String(字符串)
String是简单的 key-value 键值对,value 不仅可以是 String,也可以是数字。String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
String是最常用的一种数据类型,普通的key/value存储都可以归为此类,很常见的场景用于统计网站访问数量,当前在线人数等。incr命令(++操作)
b. List(列表)
Redis列表是简单的字符串列表,可以类比到C++中的std::list,简单的说就是一个链表或者说是一个队列。可以从头部或尾部向Redis列表添加元素。列表的最大长度为2^32 - 1,也即每个列表支持超过40亿个元素。
Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表、粉丝列表等都可以用Redis的list结构来实现,再比如有的应用使用Redis的list类型实现一个简单的轻量级消息队列,生产者push,消费者pop/bpop。
c. Hash(字典,哈希表)
类似C#中的dict类型或者C++中的hash_map类型。
Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
假设有多个用户及对应的用户信息,可以用来存储以用户ID为key,将用户信息序列化为比如json格式做为value进行保存。
d. Set(集合)
可以理解为一堆值不重复的列表,类似数学领域中的集合概念,且Redis也提供了针对集合的求交集、并集、差集等操作。
set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。
Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
又或者在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。
e. Sorted Set(有序集合)
Redis有序集合类似Redis集合,不同的是增加了一个功能,即集合是有序的。一个有序集合的每个成员带有分数,用于进行排序。
Redis有序集合添加、删除和测试的时间复杂度均为O(1)(固定时间,无论里面包含的元素集合的数量)。列表的最大长度为2^32- 1元素(4294967295,超过40亿每个元素的集合)。
Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
又比如用户的积分排行榜需求就可以通过有序集合实现。还有上面介绍的使用List实现轻量级的消息队列,其实也可以通过Sorted Set实现有优先级或按权重的队列。