SpringBoot整合Redis
Spring Boot Data(数据) Redis 中提供了Redistemplate和StringRedistemplate,其中StringRedistemplate
是Redistemplate
的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,Redistemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedistemplate的两个泛型都是String,意味着StringRedistemplate的key和value都只能是字符串。
注意:
-
springboot 2.x后 ,原来使用的 Jedis 被 lettuce 替换。
-
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来替换这个默认的!
public Redistemplate<Object, Object> redistemplate(RedisConnectionFactory redisConnectionFactory)
throws UnkNownHostException {
// 默认的 Redistemplate 没有过多的设置,redis 对象都是需要序列化!
// 两个泛型都是 Object,Object 的类型,我们后使用需要强制转换 <String,Object>
Redistemplate<Object, Object> template = new Redistemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
//由于String是redis中最常使用的类型,所以单独提一个bean!
public StringRedistemplate stringRedistemplate(RedisConnectionFactory redisConnectionFactory)
throws UnkNownHostException {
StringRedistemplate template = new StringRedistemplate();
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
@Autowired
private StringRedistemplate stringRedistemplate; //对字符串支持比较友好,不能存储对象
@Autowired
private Redistemplate redistemplate; //存储对象
@Test
public void testRedistemplate(){
System.out.println(redistemplate);
//设置redistemplate值使用对象序列化策略
redistemplate.setValueSerializer(new JdkSerializationRedisSerializer());//指定值使用对象序列化
//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",-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
*/
@Test
public void testBoundKey(){
BoundValueOperations<String, String> nameValueOperations = stringRedistemplate.boundValueOps("name");
nameValueOperations.set("1");
//yuew
nameValueOperations.set("2");
String s = nameValueOperations.get();
System.out.println(s);
}
//hash相关操作 opsForHash
@Test
public void testHash(){
stringRedistemplate.opsForHash().put("maps","name","qinyu");
Object o = stringRedistemplate.opsForHash().get("maps", "name");
System.out.println(o);
}
//zset相关操作 opsForZSet
@Test
public void testZSet(){
stringRedistemplate.opsForZSet().add("zsets","qinyu",10);
Set<String> zsets = stringRedistemplate.opsForZSet().range("zsets", 0, -1);
zsets.forEach(value-> System.out.println(value));
}
//set相关操作 opsForSet
@Test
public void testSet(){
stringRedistemplate.opsForSet().add("sets","xiaosan","xiaosi","xiaowu");
Set<String> sets = stringRedistemplate.opsForSet().members("sets");
sets.forEach(value-> System.out.println(value));
}
//list相关的操作opsForList
@Test
public void testList(){
// stringRedistemplate.opsForList().leftPushAll("lists","张三","李四","王五");
List<String> lists = stringRedistemplate.opsForList().range("lists", -1);
lists.forEach(key -> System.out.println(key));
}
//String相关的操作 opsForValue
@Test
public void testString(){
//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相关的操作
@Test
public void test(){
Set<String> keys = stringRedistemplate.keys("*");//查看所有key
Boolean 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
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.Redistemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
// 自己定义一个 Redistemplate
@Bean
@SuppressWarnings("all")
public Redistemplate<String, Object> redistemplate(RedisConnectionFactory factory) {
// 我们为了自己开发方便,一般直接使用 <String,Object>
Redistemplate<String, Object> template = new Redistemplate<String,Object>();
template.setConnectionFactory(factory);
// Json序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setobjectMapper(om);
// String 的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 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 -
网络
bind 127.0.0.1 # 绑定的ip protected-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 notice logfile "" # 日志的文件位置名 databases 16 # 数据库的数量,默认是 16 个数据库 always-show-logo yes # 是否总是显示logo
-
快照
持久化, 在规定的时间内,执行了多少次操作,则会持久化到文件
.rdb. aof
redis 是内存数据库,如果没有持久化,那么数据断电及失!# 如果900s内,如果至少有一个1 key进行了修改,我们及进行持久化操作 save 900 1 # 如果300s内,如果至少10 key进行了修改,我们及进行持久化操作 save 300 10 # 如果60s内,如果至少10000 key进行了修改,我们及进行持久化操作 save 60 10000 # 之后学习持久化,会自己定义这个测试! stop-writes-on-bgsave-error yes # 持久化如果出错,是否还需要继续工作! 默认保存出错的话停止操作 rdbcompression yes # 是否压缩 rdb 文件,需要消耗一些cpu资源! rdbchecksum yes # 保存rdb文件的时候,进行错误的检查校验! dir ./ # rdb 文件保存的目录!
-
Security 安全
127.0.0.1:6379> ping PONG 127.0.0.1:6379> config get requirepass # 获取redis的密码 1) "requirepass" 2) "" 127.0.0.1:6379> config set requirepass "123456" # 设置redis的密码 OK 127.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 # 使用密码进行登录! OK 127.0.0.1:6379> config get requirepass 1) "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算法的key 3、volatile-random:随机删除即将过期key 4、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对比
命令 save bgsave IO类型 同步 异步 阻塞? 是 是(阻塞发生在fock(),通常非常快) 复杂度 O(n) O(n) 优点 不会消耗额外的内存 不阻塞客户端命令 缺点 阻塞客户端命令 需要fock子进程,消耗内存
自定义工具类
可以参考下面的链接
https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html
原文地址:https://blog.csdn.net/qq_43585922" target="_blank" rel="noopener" title="秦 羽">秦 羽</a> <img class="article-time-img article-heard-img" src="https://csdnimg.cn/release/blogv2/dist/p
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。