SpringBoot整合Redis
Spring Boot Data(数据) Redis 中提供了RedisTemplate和StringRedisTemplate,其中
StringRedisTemplate
是
RedisTemplate
的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。
注意:
- 使用RedisTemplate默认是将对象序列化到Redis中,所以放入的对象必须实现对象序列化接口
- springboot 2.x后 ,原来使用的 Jedis 被 lettuce 替换。
- jedis:采用的直连,多个线程操作的话,是不安全的。如果要避免不安全,使用jedis pool连接池!更像BIO模式
- lettuce:采用netty,实例可以在多个线程中共享,不存在线程不安全的情况!可以减少线程数据了,更像NIO模式
1 环境准备
1.1.引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
1.2.配置application.propertie
# springboot所有的配置类都有一个自动配置类, xxxAutoConfiguration
# 自动配置类都会绑定一个properties 的配置文件,xxxProperties
spring.redis.host=127.0.0.1 #localhost
spring.redis.port=6379
spring.redis.database=0
源码分析:
@Bean@ConditionalOnMissingBean(name ="redisTemplate")// 可以自己定义一个redisTemplate来替换这个默认的!publicRedisTemplate<Object,Object>redisTemplate(RedisConnectionFactory redisConnectionFactory)throwsUnknownHostException{// 默认的 RedisTemplate 没有过多的设置,redis 对象都是需要序列化!// 两个泛型都是 Object, Object 的类型,我们后使用需要强制转换 <String, Object>RedisTemplate<Object,Object> template =newRedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);return template;}@Bean@ConditionalOnMissingBean//由于String是redis中最常使用的类型,所以单独提一个bean!publicStringRedisTemplatestringRedisTemplate(RedisConnectionFactory redisConnectionFactory)throwsUnknownHostException{StringRedisTemplate template =newStringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);return template;}
1.3. 连接测试
可以看一下第二节
redisTemplate 操作不同的数据类型,api和我们的指令是一样的
opsForValue 操作字符串 类似String
opsForList 操作List 类似List
opsForSet
opsForHash
opsForZSet
opsForGeo
opsForHyperLogLog
除了进本的操作,我们常用的方法都可以直接通过redisTemplate操作,比如事务,和基本的CRUD
获取redis的连接对象
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.flushDb();
connection.flushAll();
2 使用StringRedisTemplate和RedisTemplate
@AutowiredprivateStringRedisTemplate stringRedisTemplate;//对字符串支持比较友好,不能存储对象@AutowiredprivateRedisTemplate redisTemplate;//存储对象@TestpublicvoidtestRedisTemplate(){System.out.println(redisTemplate);//设置redistemplate值使用对象序列化策略
redisTemplate.setValueSerializer(newJdkSerializationRedisSerializer());//指定值使用对象序列化//redisTemplate.opsForValue().set("user",new User("1","qinyu",99,new Date()));User user =(User) redisTemplate.opsForValue().get("user");System.out.println(user);//Set keys = redisTemplate.keys("*");//keys.forEach(key -> System.out.println(key));/*Object name = redisTemplate.opsForValue().get("name");
System.out.println(name);*///Object qinyu= redisTemplate.opsForValue().get("qinyu");//System.out.println(qinyu);/*redisTemplate.opsForValue().set("name","xxxx");
Object name = redisTemplate.opsForValue().get("name");
System.out.println(name);*//*redisTemplate.opsForList().leftPushAll("lists","xxxx","1111");
List lists = redisTemplate.opsForList().range("lists", 0, -1);
lists.forEach(list-> System.out.println(list));*/}/*key的绑定操作 如果日后对某一个key的操作及其频繁,可以将这个key绑定到对应redistemplate中,日后基于绑定操作都是操作这个key
boundValueOps 用来对String值绑定key
boundListOps 用来对List值绑定key
boundSetOps 用来对Set值绑定key
boundZsetOps 用来对Zset值绑定key
boundHashOps 用来对Hash值绑定key
*/@TestpublicvoidtestBoundKey(){BoundValueOperations<String,String> nameValueOperations = stringRedisTemplate.boundValueOps("name");
nameValueOperations.set("1");//yuew
nameValueOperations.set("2");String s = nameValueOperations.get();System.out.println(s);}//hash相关操作 opsForHash@TestpublicvoidtestHash(){
stringRedisTemplate.opsForHash().put("maps","name","qinyu");Object o = stringRedisTemplate.opsForHash().get("maps","name");System.out.println(o);}//zset相关操作 opsForZSet@TestpublicvoidtestZSet(){
stringRedisTemplate.opsForZSet().add("zsets","qinyu",10);Set<String> zsets = stringRedisTemplate.opsForZSet().range("zsets",0,-1);
zsets.forEach(value->System.out.println(value));}//set相关操作 opsForSet@TestpublicvoidtestSet(){
stringRedisTemplate.opsForSet().add("sets","xiaosan","xiaosi","xiaowu");Set<String> sets = stringRedisTemplate.opsForSet().members("sets");
sets.forEach(value->System.out.println(value));}//list相关的操作opsForList@TestpublicvoidtestList(){// stringRedisTemplate.opsForList().leftPushAll("lists","张三","李四","王五");List<String> lists = stringRedisTemplate.opsForList().range("lists",0,-1);
lists.forEach(key ->System.out.println(key));}//String相关的操作 opsForValue@TestpublicvoidtestString(){//stringRedisTemplate.opsForValue().set("166","好同学");String s = stringRedisTemplate.opsForValue().get("166");System.out.println(s);Long size = stringRedisTemplate.opsForValue().size("166");System.out.println(size);}//key相关的操作@Testpublicvoidtest(){Set<String> keys = stringRedisTemplate.keys("*");//查看所有keyBoolean name = stringRedisTemplate.hasKey("name");//判断某个key是否存在
stringRedisTemplate.delete("age");//根据指定key删除
stringRedisTemplate.rename("","");//修改key的名称
stringRedisTemplate.expire("key",10,TimeUnit.HOURS);//设置key超时时间 参数1:设置key名 参数2:时间 参数3:时间的单位
stringRedisTemplate.move("",1);//移动key}
3 自定义RedisTemplate
importcom.fasterxml.jackson.annotation.JsonAutoDetect;importcom.fasterxml.jackson.annotation.PropertyAccessor;importcom.fasterxml.jackson.databind.ObjectMapper;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;@ConfigurationpublicclassRedisConfig{// 自己定义一个 RedisTemplate@Bean@SuppressWarnings("all")publicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactory factory){// 我们为了自己开发方便,一般直接使用 <String, Object>RedisTemplate<String,Object> template =newRedisTemplate<String,Object>();
template.setConnectionFactory(factory);// Json序列化配置Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =newJackson2JsonRedisSerializer(Object.class);ObjectMapper om =newObjectMapper();
om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);// String 的序列化StringRedisSerializer stringRedisSerializer =newStringRedisSerializer();// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();return template;}}
4 配置文件
启动的时候,就通过配置文件来启动!
单位 容量单位不区分大小写,G和GB有区别
- 配置文件 unit单位 对大小写不敏感!
- 包含 可以使用 include 组合多个配置问题 例如:include /path/to/local.conf
- 网络
bind127.0.0.1 # 绑定的ipprotected-mode yes# 保护模式port 6379# 端口设置
- 通用 GENERAL
daemonize yes# 以守护进程的方式运行(就是后台运行),默认是 no,我们需要自己开启为yes!pidfile /var/run/redis_6379.pid # 如果以后台的方式运行,我们就需要指定一个 pid 文件!# 日志# Specify the server verbosity level.# This can be one of:redis 是内存数据库,如果没有持久化,那么数据断电及失!REPLICATION 复制,我们后面讲解主从复制的,时候再进行讲解SECURITY 安全可以在这里设置redis的密码,默认是没有密码!# debug (a lot of information, useful for development/testing)# verbose (many rarely useful info, but not a mess like the debug level)# notice (moderately verbose, what you want in production probably) 生产环境# warning (only very important / critical messages are logged)loglevel noticelogfile ""# 日志的文件位置名databases 16# 数据库的数量,默认是 16 个数据库always-show-logo yes# 是否总是显示LOGO
- 快照持久化, 在规定的时间内,执行了多少次操作,则会持久化到文件
.rdb. aof
redis 是内存数据库,如果没有持久化,那么数据断电及失!# 如果900s内,如果至少有一个1 key进行了修改,我们及进行持久化操作save 9001# 如果300s内,如果至少10 key进行了修改,我们及进行持久化操作save 30010# 如果60s内,如果至少10000 key进行了修改,我们及进行持久化操作save 6010000# 之后学习持久化,会自己定义这个测试!stop-writes-on-bgsave-error yes# 持久化如果出错,是否还需要继续工作! 默认保存出错的话停止操作rdbcompression yes# 是否压缩 rdb 文件,需要消耗一些cpu资源!rdbchecksum yes# 保存rdb文件的时候,进行错误的检查校验!dir ./ # rdb 文件保存的目录!
- SECURITY 安全可以在这里设置redis的密码,默认是没有密码!
127.0.0.1:6379>pingPONG127.0.0.1:6379> config get requirepass # 获取redis的密码1)"requirepass"2)""127.0.0.1:6379> config set requirepass "123456"# 设置redis的密码OK127.0.0.1:6379> config get requirepass # 发现所有的命令都没有权限了(error) NOAUTH Authentication required.127.0.0.1:6379>ping(error) NOAUTH Authentication required.127.0.0.1:6379> auth 123456# 使用密码进行登录!OK127.0.0.1:6379> config get requirepass1)"requirepass"2)"123456"
- 限制 CLIENTS
maxclients 10000# 设置能连接上redis的最大客户端的数量maxmemory <bytes># redis 配置最大的内存容量maxmemory-policy noeviction # 内存到达上限之后的处理策略# redis 中的默认的过期策略是 volatile-lru 。1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)2、allkeys-lru : 删除lru算法的key3、volatile-random:随机删除即将过期key4、allkeys-random:随机删除5、volatile-ttl : 删除即将过期的6、noeviction : 永不过期,返回错误------------------------------------------------# 设置方式config set maxmemory-policy volatile-lru
- APPEND ONLY 模式 aof配置
appendonly no # 默认是不开启aof模式的,默认是使用rdb方式持久化的,在大部分所有的情况下,rdb完全够用!appendfilename "appendonly.aof"# 持久化的文件的名字# appendfsync always # 每次修改都会 sync。消耗性能appendfsync everysec # 每秒执行一次 sync,可能会丢失这1s的数据!# appendfsync no # 不执行 sync,这个时候操作系统自己同步数据,速度最快!
- bgsave bgsave 是异步进行,进行持久化的时候,redis 还可以将继续响应客户端请求 ;bgsave和save对比命令savebgsaveIO类型同步异步阻塞?是是(阻塞发生在fock(),通常非常快)复杂度O(n)O(n)优点不会消耗额外的内存不阻塞客户端命令缺点阻塞客户端命令需要fock子进程,消耗内存
自定义工具类
可以参考下面的链接
https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html
版权归原作者 秦 羽 所有, 如有侵权,请联系我们删除。