SpringBoot 整合Redis
构建springboot项目;项目结构
一、springboot整Redis
1、pom.xml文件添加redis依赖
<!--
说明:在SpringBoot2.x之后,原来使用的Jedis被替换为了lettuce
Jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用Jedis pool 连接池 ! 更像BIO模式
lettuce:采用netty,实例可以再多个线程中进行共享,不存在线程不安全的情况,可以减少线程数据了,更像NIO模式
-->
<!--redis 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
2、application.properties文件配置redis
# springboot所有的配置类,都有一个自动配置类,RedisAutoConfiguration
# 自动配置类都会绑定一个properties配置文件,RedisProperties
#配置redis
spring.redis.host=192.168.122.1
spring.redis.port=6379
spring.redis.password=redisRoot
3、在test类测试,操作redis
@SpringBootTest
class SpbApplicationTests {
@Autowired
private RedisTemplate redisTemplate; //注入RedisTemplate
@Test
void contextLoads() {
redisTemplate.opsForValue().set("key","studyRedis");
String result = (String)redisTemplate.opsForValue().get("key");
System.out.println(result);//studyRedis
}
}
二:自定义RedisTemplate
1、创建新的包config包,并创建RedisConfig类
@Configuration
public class RedisConfig {
//自定义RedisTemplate,固定写法
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
//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;
}
}
2、测试
@SpringBootTest
class SpbApplicationTests {
//@Autowired
//private RedisTemplate redisTemplate; //注入原RedisTemplate
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate ;//注入自定义的RedisTemplate
@Test
void contextLoads() {
redisTemplate.opsForValue().set("key","studyRedis");
String result = (String)redisTemplate.opsForValue().get("key");
System.out.println(result);
}
}
三:Redis.conf详解
1、配置文件unit单位对大小写不敏感
2、多个配置文件组成一个
3、网络配置
bind 127.0.0.1 #绑定的ip
protected-mode yes #保护模式
port 6379 #端口设置
4、通用配置
daemonize yes #以守护进程的方式运行,默认为no,需要改为yes
pidfile /var/run/redis_6379.pid #如果以守护进程运行 ,我需要指定一个pid文件
# 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,默认开启
5、快照SNAPSHOTTING:持久化是会用到,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb和.aof
#save 时间(s)
save 900 1 #如果在900s内,至少有1个key进行了修改,就进行持久化操作
save 300 10#如果在300s内,至少有10个key进行了修改,就进行持久化操作
save 60 10000#如果在60s内,至少有1w个key进行了修改,就进行持久化操作
stop-writes-on-bgsave-error yes #持久化出错,是否还需要继续工作
rdbcompression yes #是否压缩rdb文件,需要消耗CPU资源
rdbchecksum yes #保存rdb文件时,进行错误的检查校验
dir ./ #rdb 文件保存的目录
6、REPLICATION复制(主从复制)
7、SECURITY 安全
requirepass redisRoot #设置redis密码 :redisRoot
config set requirepass "redisRoot" #配置redis密码
auth redisRoot #使用密码登录
config get requirepass #查看密码
8、CLIENTS 限制
maxclients 10000 #最大的客户端连接数为1w
maxmemory <bytes> #最大内存设置
maxmemory-policy noeviction #内存到达上限之后的处理策略
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除lru算法的key
3、volatile-random:随机删除即将过期key
4、allkeys-random:随机删除
5、volatile-ttl : 删除即将过期的
6、noeviction : 永不过期,返回错误
9、APPEND ONLY MODE aof配置
appendonly no #默认是不开启的,默认是使用rdb方式持久化,在大部分所有的情况下,rdb完全够用
appendfilename "appendonly.aof" #持久化的文件的名字
# appendfsync always #每次修改都会同步,消耗性能
appendfsync everysec #每秒执行一次同步,可能会丢失这1s的数据
# appendfsync no #不执行同步,效率最高,一般不使用
Redis为持久化
Redis为持久化提供了两种方式:
- RDB:在指定的时间间隔能对你的数据进行快照存储。
- AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据。
RDB持久化配置:
# 时间策略
save 900 1
save 300 10
save 60 10000
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
AOF的持久化配置
# 是否开启aof
appendonly yes
# 文件名称
appendfilename "appendonly.aof"
# 同步方式
appendfsync everysec
# aof重写期间是否同步
no-appendfsync-on-rewrite no
# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 加载aof时如果有错如何处理
aof-load-truncated yes
# 文件重写策略
aof-rewrite-incremental-fsync yes
appendfsync everysec 它其实有三种模式:
always:把每个写命令都立即同步到aof,很慢,但是很安全
everysec:每秒同步一次,是折中方案
no:redis不处理交给OS来处理,非常快,但是也最不安全
一般情况下都采用 everysec 配置,这样可以兼顾速度与安全,最多损失1s的数据。
aof-load-truncated yes 如果该配置启用,在加载时发现aof尾部不正确是,会向客户端写入一个log,但是会继续执行,如果设置为 no ,发现错误就会停止,必须修复后才能重新加载。
RDB方式原理:当redis需要做持久化时(执行SAVA或者BGSAVA命令,或者是达到配置条件时执行),redis会fork一个子进程,子进程将数据写到磁盘上一个临时RDB文件中,当子进程完成写临时文件后,将原来的RDB替换掉(默认文件名为dump.rdb)
RDB优缺点:
定时备份,Redis效率高,但是容易造成数据丢失,丢失的多少和备份策略有关
AOF方式原理:AOF就可以做到全程持久化,Redis每执行一个修改数据的命令,都会把这个命令添加到AOF文件中,当Redis重启时,将会读取AOF文件进行“重放”以恢复到 Redis关闭前的最后时刻。
AOF优缺点
AOF基本可以保证数据不丢失,但是AOF持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。
redis 发布订阅
redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息.
订阅端(订阅者:subscribe):
127.0.0.1:6379> subscribe redis-world #订阅redis-world频道
1) "subscribe"
2) "redis-world"
3) (integer) 1
1) "message" #消息
2) "redis-world" #频道
3) "welcome redis world" #消息内容
发送端(发送者:publish):
127.0.0.1:6379> publish redis-world "welcome redis world" #发布者发布消息到频道
(integer) 1
使用场景:
1、实时消息
2、在线聊天
3、关注、订阅
更为复杂的使用消息中间件来实现
Redis主从复制
主从复制,是指 将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。master以写为主,slave以读为主。大部分情况下80%的操作是读数据。
主从复制的作用主要包括:
1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
2、故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
3、负载均衡:主从复制的基础上,配合读写分离,可以由主节点提供写服务,从节点提供读服务,分担服务器负载,可以提高服务器的并发量。
4、高可用基石:除上述作用外,主从复制还是哨兵和集群能够实施的基础,因此主从复制是Redis的高可用的基础。
一般来说,至少3台服务器,一主二从。(单个redis的内存不好超过20G,最好搭建集群)
环境配置:(只配置从库,因为redis默认为主库)
127.0.0.1:6379> info replication #当前库的信息
# Replication
role:master #当前库的角色
connected_slaves:0 #连接从库的数量
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
复制3个配置文件:
1、端口(端口的话,自己记得就好)
2、pid名
3、log日志文件名
4、dump.rdb名
配置完成后,分别启动数据库。当前3台数据库默认都是主节点,只配置充当从节点的数据库,对它们配置主节点的信息。
slaveof ip port #配置主机的ip和端口号
当前从节点的配置是通过命令行进行配置的,是暂时的。在实际应用是在redis配置文件中配置的,永久有效,当从节点启动服务就为扮演从节点的角色。
#replicaof <masterip> <masterport> 在配置文件中解注这行,添加主机的ip和端口号即可.
从机只可读,不可写。
主从模式结构1是这样子的:
|
|--slave1(从机)
master--|
|--slave2(从机)
|
测试:
主机断开连接,从机会依然连接到主机,但是没有写操作了。主机服务正常了,从机可以正常获取到主机写入的数据。如果从机宕机,主机进行了写操作,从机再次开启服务,数据会立马同步到数据。(如果从机是使用命令配置的,开启服务后会变为主机,需要再次配置主机信息使自己变为从机,主机的数据会同步到当前从机)
复制原理:
slave(从机)启动成功连接到master(主机)后会发送一个sync(同步)命令,
主机接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,主机将传送整个数据文件到从机,并完成一次完全同步。
全量复制:而从机服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:主机继续新的所有收集到的修改命令一次传给从机,完成同步,但是只要是重新连接主机,一次完全同步(全量复制)将自动执行
主从模式结构2是这样子的:
(主机) (从机/主机) (从机)
master--|--slave1--|slave2
如果master断开了,slave1和slave2没有了主节点,现在可以手动在slave1上配置slaveof no one,是自己成为主机
意思两种模式,在实际开发的过程中都不用。不够灵活,所以,就引出了哨兵模式。
Redis哨兵模式
监控后台主机是否存活,如果不存活了就需要在从机中选举一个作为主机。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,单独运行。哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个Redis实例。
哨兵的两个作用:
1、通过发送命令,让Redis服务器返回监控其运行状态,包括服务器和从服务器。
2、当哨兵检测到主机宕机,会自动将从机切换成主机。
一般保证系统的能正常的选举主机,一个哨兵是不够的,一般会设计多个哨兵进行监控,各个哨兵之间还会进行监控,形成多哨兵模式。
多个哨兵模式:当一个哨兵检测到主机不可用,这个现象称为主观下线;当所有的哨兵检测到主机不可用,才认为主机不可用了;哨兵之间会进行一次投票,投票结果由一个哨兵发起,进行failover(故障转移)操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
哨兵配置(单个)(默认30秒后会选举出一个主机)
1、创建sentinel.conf文件
sentinel monitor myredis 127.0.0.1 6379 1 (主机 端口 1:代表主机不可用,哨兵通过投票得到的最多票数从从机中选出一台作为主机)
2、启动哨兵 redis-sentinel 配置文件sentinel.conf
当选取主机后,原主机如果正常服务,只能作为当前的主机的从机。
哨兵模式的优缺点:
优点:1)哨兵集群,基于主从复制模式,所有的主从配置优点;
2)主从可以切换,故障可以转移,系统的可用性会更好
3)哨兵模式就是主从模式的升级,由手动到自动,功能更加灵活,强大
缺点: 1)Redis在线扩容繁琐,集群容量一旦到达上限,扩容困难
2)实现哨兵模式的配置繁琐,配置选择项太多