redis是什么
1 redis是远程字段服务 是用c编写的 基于内存持久化的key-value数据库,
2 redis是key-value存储系统,他支持value类型有String,list,set,zset,hash;操作都是原子性,为了提供效率数据都是缓存在内存中的,也可以持久化到磁盘中
-redis特点
1 读写效率高,高速缓存
2 多样数据类型
3 支持持久化
4 操作原子性
5 主从复制redis的基本知识
1 端口是默认是6379 是一个明星的名字
2 默认有16个数据库 默认使用选择0号数据库
3 select 1 可以进行切换数据库
4 统一密码管理 dbsize 查看当前数据库的key数量
5 flushdb 清空当前库
6 flushall 清空所有库
7 为什么redis是单线程还效率高呢
1数据操作都是基于内存中运行没有io读写
2 没有多线程带来的弊端redis数据类型
- redis数据类型 redis是key-value结构类型的数据库 - key键 1 keys * 查看当前库中所有的key 2 exists key 判断某个key是否存 存在返回1 不存在返回0 3 move key db 将当前数据库中的key移动到指定的数据库db中 move k1 6 4 type key 判断当前可以所存储的value是什么类型 5 del key 删除已存在的key 返回删除成功的个数 6 expire key time 设置key的存活时间 设置成功返回1 7 ttl key 查看当前key的存活时间 8 persist key 取消key的过期时间 就是不过期了 移除成功后返回1 否则返回0
redis持久化
redis数据都是存放到内存中的,没有配置持久化的话,redis重启后数据就会消失,开启redis持久化功能后,将数据保存到磁盘上,当redis
重启后可以从磁盘中恢复数据。
两种持久化方法
1 RDB (redis data base)
2 AOF(Append only file)
RDB是什么?
在指定时间间隔内将内存中的数据进行一次快照,写入到磁盘中,在做恢复时也是恢复快照内容,
dump.rdb文件
rdb保存的文件是将持久化数据保存到这个文件中的,在redis.conf配置文件中,可以看到dbfilename dump.rdb
默认在bin目录下存放dump.rdb文件。
配置文件中设置快照的启动
在snapshotting模块中
save 时间秒 变化值 这个是设置值的变化
示例 save 3600 1 表示一个小时内 一个key发生了变化则持久化一次
在执行flushall 命令后 会触发rdb规则
手动触发rdb持久化命令
1 save 开始执行持久化作业,期间不能处理其他命令
2 bgsave redis后台执行快照,同时还可以继续处理请求
在配置文件中设置
stop-writes-on-bgsave-error 默认值是yes,当redis无法写入磁盘的话,直接关闭redis写操作
rdbcompression 默认值是yes 对于存储到磁盘的快照,进行压缩,
rdbchecksum 默认值是yes 在存储快照时 可以使用redis进行数据校验 消耗性能
恢复数据只需要将rdb文件放到redis启动目录下,就会自动加载dump.rdb 并恢复数据
aof 持久化
1 以日志的形式来记录每一个写的操作,将写入的指令记录下来,redis在重启的时候会先读取该日志,进行指令执行来恢复数据
2 持久化过程 客户端写操作命令会被记录到aof日志中
3 在redis.conf中配置文件中默认为不开启 -appendonly no - appendfilename “appendonly.aof”
aof 和rdb保存文件路径是一样的,都是存放在启动目录bin里面
如果aof和rdb同时开启的话 redis默认是读取aof的数据
aof 启动和修复恢复
正常启动 修改appendonly no为yes 会出现appendonly.aof文件
异常恢复数据 ./redis-check-aof --fix appendonly.aof 来执行命令修复
aof 同步频率设置 appendfsync always/everysec/no 始终同步/每秒同步/操作系统来同步
文件重写机制
1 auto-aof-rewrite-min-size 100 表示重写 文件大小超过这个值
2 auto-aof-rewrite-percentage 表示目前文件大小比上一次重写的文件大这个多值才可以
springboot整合redis
- 添加依赖
org.springframework.boot
spring-boot-starter-data-redis
- 配置文件
spring:
redis:
host: 192.168.111.222
port: 6379
timeout: 100000
- 创建配置项目整合redis的配置
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory){
//创建一个redis模板
RedisTemplate redisTemplate = new RedisTemplate<>();
//给key设置StringRedisSerializer序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
//给value设置序列化器
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
- 常见的序列化器 StringRedisSerializer 简单字符串序列化
- JdkSerializationRedisSerializer: 序列化java对象(需要序列化的类必须实现Serializable接口)
- Jackson2JsonRedisSerializer:序列化对象(序列化带泛型的数据时,会以map的结构进行存
储,反序列化是不能将map解析成对象)
-测试
@Test
void tests(){
//操作字符串 存放对象
Redis redis = new Redis("Redis", "boy");
redisTemplate.opsForValue().set("redis",redis);
//获取数据
Redis redis1 = (Redis)redisTemplate.opsForValue().get("redis");
System.out.println(redis1);
}
redis脑裂
redis集群 有一个master 多个slave 可能会因为网络出现异常 导致出出现一个新的master ,网络恢复后 新的master会代替旧的master,但是数据是不一样的,
解决方案
min-replicas-to-write 1 最少有一个slave节点
min-replicas-max-lag 10 数据的同步和复制延迟不能超过10s
配置了这两个参数后,如果发生了脑裂 master会拒接写操作请求,缓存穿透
在高并发的请求同一个key在redis中并没有这个key,导致请求每次都会直接从数据库中进行查询,可能会导致数据库宕机,
redis没有启动缓存的作用,导致缓存穿透,解决方案
1对空置进行缓存,查询为空的值,redis也会进行缓存,缓存击穿
在redi数据库中有一个热点key正在高并发请求,而key恰好到了过期时间,此时大量请求直接访问数据库,最终可能会造成数据库压力大崩溃,
击穿是指key缓存在过期时间进行了高并发请求,导致redis没有起到缓存的作用解决方案
1 加互斥锁,对同一个key的高并发请求下进行加锁,这样可以有效进行缓存
2 设置热点数据不过期缓存雪崩
在redis中设置key的过期时间为同一个时刻,这样会导致同一个时刻下key缓存失效,所有的key请求压力直接来到数据库中,
雪崩是指不同的数据同时过期,导致请求到达数据库
击穿是指同一个数据过期导致请求到达数据库,解决方案
1 缓存key的失效时间设置成随机,防止同一个时间失效
2 设置热点不过期,redistemplate APIredisTemplate 是springdataRedis提供的操作redis的客户端
使用spring-data-redis 的redisTemplate来实现redis的访问操作
-String类型操作 1 获取缓存 redisTemplate.opsForValue.get(key) 2 添加缓存 redisTemplate.opsForValue().set(key,value); 3 添加缓存并设置过期时间 redis.Template.opsForValue().set(key,value,time,TimeUnit.SECONDS) 4 向一个key中添加一个对象 redisTemplate.opsForValue().multiSet(value) 5 获取某个key的对象 redisTemplate.opsForValue().multiGet(key) 6 批量插入数据 redisTemplate.opsForList().leftPushAll(key,value) 7 批量取出数据 redisTemplage.opsForList().range(key,0,-1) - hash类型 1 批量插入 RedisTemplate.opsForHash().putAll(KEY, value ); 2 单个删除 RedisTemplate.opsForHash().delete(key, sourceOrgId); 3 单个获取 RedisTemplate.opsForHash().get(Key, hashKey); 4 批量获取 RedisTemplate.opsForHash().entries(getUserNodeCacheKey(syncUserNode.getSourceId())); - Set类型 1 单个插入 RedisTemplate.opsForSet().add(KEY, cloudtOrgRoleInfo); 2 批量取出 RedisTemplate.opsForSet().members(KEY); 3 单个删除 RedisTemplate.opsForSet().remove( KEY, subDeleteOrgRoleUserArray[i]); 4 根据key获取Set中的所有值 RedisTemplate.opsForSet().remove( KEY, subDeleteOrgRoleUserArray[i]); 5 SET缓存的长度 redisTemplate.opsForSet().size(key); - LIST类型相关操作 1 获取list缓存的内容 redisTemplate.opsForList().range(key, start, end); 2 获取list缓存的长度 redisTemplate.opsForList().size(key); 3 将list放入缓存 redisTemplate.opsForList().rightPush(key, value); 4 将list放入缓存并设置过期时间 redisTemplate.opsForList().rightPush(key, value); expire(key, time); 5 将list放入缓存 redisTemplate.opsForList().rightPushAll(key, value);



