一、redis的简介
Redis是一个高性能的基于Key-Value结构存储的NoSQL(not only sql)开源数据库。支持多种数据结构存储。
二、redis的五种数据结构
1、string(字符串)
1. set key value: 设置指定 key 的值
2.get key 获取指定 key 的值
3.mset key value key value .... 同时设置一个或多个 key-value 对
4.mget key key .... 获取所有(一个或多个)给定 key 的值
5.incr key 将 key 中储存的数字值增一。 用于点赞 收藏
6.decr key 将 key 中储存的数字值减一
public class RedisService {
@Autowired
private StringRedisTemplate redisTemplate;
// 写入String类型数据
@Test
public void setString(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
// 获取String类型数据
@Test
public String getString(String key) {
return redisTemplate.opsForValue().get(key);
}
}
2、map(哈希)
表示redis的value类型为Hash类型,一般存放对象数据。
1. hset key field value 将哈希表 key 中的字段 field 的值设为 value 。
2. hget key field 获取存储在哈希表中指定字段的值/td>
3. hget key 获取在哈希表中指定 key 的所有字段和值
4. hkeys key 获取所有哈希表中的字段
5.hvals key 获取哈希表中所有值
3、list(列表)
value 可以是一个队列---该队列的值可以重复而且有序。
1. LPush key value value value... 将一个或多个值插入到列表头部
2. lrange key start end 获取列表指定范围内的元素
Redis Lrange 返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
3.lpop key 移出并获取列表的第一个元素
4、set(集合)
无序不允许重复.
1. sadd key value value ....向集合添加一个或多个成员
2.smemebers key 返回集合中的所有成员
3.SRANDMEMBER KEY 随机获取一个或多个元素
4.sinter key key: 返回给定所有集合的交集
5、zset(有序集合)
和上面的set区别在于多了一个score分数列----- 排行耪
1.zadd key score value score value :向有序集合添加一个或多个成员,或者更新已存在成员的分数
2.zrange key 通过索引区间返回有序集合成指定区间内的成员
3.ZREVRANK key start end 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
三、使用Redis要解决的三种问题
1.缓存雪崩
缓存雪崩是指大量的应用请求无法在Redis缓存中进行处理,从而使得大量请求发送到数据库层,导致数据库压力过大甚至宕机。
产生原因:1.大面积的缓存失效2.Redis服务故障宕机
解决方案:
均匀过期:给热点数据设置不同的过期时间,给每个key的失效时间加一个随机值
集群部署:构建 Redis 缓存高可靠集群。 如果 Redis 缓存的主节点故障宕机了,从节点还可以切换成为主节点,继续提供缓存服务,避免了由于缓存实例宕机而导致的缓存雪崩问题
2.缓存穿透
缓存穿透指用户要访问的数据既不在缓存中也不在数据库中,导致用户每次请求该数据时都要去数据库查一遍,然后返回空。如果有恶意攻击者不断请求这种系统不存在的数据,会导致数据库压力过大,严重会击垮数据库。
解决方案:
布隆过滤器:快速判断数据是否存在,避免从数据库中查询数据是否存在,减轻数据库压力。
3.缓存击穿
缓存击穿是指某个访问非常频繁的热点数据,大量并发请求集中在这一个点访问,在这个Key失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿了一个洞。
解决方案:
使用分布式锁,如果是单体应用的话使用互斥锁
四、Redis的持久化方式
AOF:记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集
RDB:可以在指定的时间间隔内生成数据集的时间点快照
五、Redis与mysql的数据一致性
双写策略:进行写操作时,首先将数据写入MySQL,然后再将数据写入Redis。这确保了数据的一致性,因为MySQL是持久性数据库,数据写入后会持久保存。Redis则用于提高读取性能。
使用消息队列:可以使用消息队列,例如RabbitMQ或Kafka,来确保Redis和MySQL之间的数据一致性。当数据发生更改时,将消息发送到消息队列,然后由消费者负责更新Redis和MySQL中的数据。这种方法可以实现异步数据更新,提高性能和可扩展性。
订阅mysql的binlog日志:一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新
分布式中使用延迟双删:删除redis,更新数据库,延时500毫秒,删除redis。防止第一次删除Redis之后,有访问去读数据库,然后Redis的数据还是以前的数据,所以二次删除。
六、Redis的过期策略
用于管理过期数据的策略,这些策略决定了在何时自动删除过期键(Key)以释放内存
定时过期策略 (TTL - Time To Live):Redis中的每个键可以关联一个过期时间(TTL)。当一个键设置了TTL后,它将在一定时间内自动过期。
惰性删除策略:Redis不会主动检查键是否过期。而是在访问某个键时,如果发现该键已过期,Redis会立即删除它并返回空值。
定期删除策略:Redis周期性地(默认每秒钟10次)从所有已设置过期时间的键中选择一部分,然后删除其中已经过期的键
七、Redis的淘汰算法
Redis使用不同的淘汰(Eviction)算法来管理内存,以处理内存不足的情况。
第一种,采用 LRU (Least Recently Used)策略 ,就是把不经常使用的 key 淘汰掉 .
第二种 ,采用 LFU (Least Frequently Used)策略 ,它在 LRU 算法上做了优化 ,增加了数据访问次数 ,从而确保淘汰的是非热点 key。
第三种 ,随机策略 ,也就是随机删除一些 key
第四种 ,ttl 策略 ,从设置了过期时间的 key 里面 ,挑选出过期时间最近的 key 进行优先淘汰
第五种 ,当内存不够的时候 ,直接报错 ,这是默认的策略。
八、springboot集成Redis实现布隆过滤器
可以使用现有的Java布隆过滤器库,如Google Guava的“BloomFilter
”,或者使用第三方库如Redisson来实现布隆过滤器
下面是一个使用Redisson实现布隆过滤器的示例:
需要加入redission的依赖
<!-- redis的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- redission的依赖 -->
<dependency>
<groupId>se.svt.oss</groupId>
<artifactId>redisson-starter</artifactId>
<version>1.1.3</version>
</dependency>
package com.zsc.service.impl;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BloomFilterService {
@Autowired
private RedissonClient redissonClient;
public void addToBloomFilter(String filterName, String value) {
RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(filterName);
bloomFilter.add(value);
}
public boolean checkExistsInBloomFilter(String filterName, String value) {
RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(filterName);
return bloomFilter.contains(value);
}
}
package com.zsc.controller;
import com.zsc.service.impl.BloomFilterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/bloom-filter")
public class BloomFilterController {
@Autowired
private BloomFilterService bloomFilterService;
@PostMapping("/add")
public void addToBloomFilter(@RequestParam String filterName, @RequestParam String value) {
bloomFilterService.addToBloomFilter(filterName, value);
}
@GetMapping("/check")
public boolean checkExistsInBloomFilter(@RequestParam String filterName, @RequestParam String value) {
return bloomFilterService.checkExistsInBloomFilter(filterName, value);
}
}
九、springboot集成Redis实现分布式锁
待完善
十、springboot集成Redis实现幂等操作防止重复提交
在向后端提交请求之前,后端先返回一个token,且存在Redis中一个。当请求带着token到后端,先从Redis中拿出token比较,是正确的,就操作数据库,且删除token。后续再有相同请求,因为没有token,就返回消息已操作。
十一、操作Redis的两种方式
1.redisTemplate类
2.注解:
@EnableCaching ,在applicaction主类上使用 @EnableCaching 注解能够开启缓存注解功能
@Cacheput用于数据库数据增加的时候,将方法的返回值放到缓存中
@Cacheable用于对数据库修改和查找的时候,在方法执行前 Spring 会先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;若没有数据,调用方法并将方法返回值放到缓存中
@CacheEvict用于对数据库删除的时候,将一条或多条数据从缓存中删除
十二、Redis的三种集群
1.主从模式:
配置主从模式---配从不配主,
命令slaveof 主节点ip 主节点port
缺点,如果主节点挂掉,整个集群挂掉
2.哨兵模式:
开启哨兵服务:redis-sentinel sentinel.conf
有选举的方法,如果主节点宕机后,从节点上位
3.集群
去中心化,且每个节点的数据是不一样的,能很好的利用Redis宝贵的内存。