第一章 Redis入门
Redis诞生于2009年全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。其主要特征如下:
-
键值(key-value)型,value支持多种不同数据结构,功能丰富;
-
单线程,每个命令具备原子性;
-
低延迟,速度快(基于内存、IO多路复用、良好的编码);
-
支持数据持久化;
-
支持主从集群、分片集群;
-
支持多语言客户端;
第二章 Redis基本知识
2.1 节 Reids 多路复用
在Redis6/7之前是单线程架构,之后是多线程架构,采用多个IO线程来处理网络请求,提高网络请求处理的并行度。但是,Redis的多IO线程只是用来处理网络请求的,对于读写操作命令Redis仍然使用单线程来处理。
2.2 节 Redis 默认16 库
第三章 Redis 数据类型
3.1 节 String
3.2 节 List
3.3 节 Set
3.4 节 Hash
3.5 节 Zset
3.6 节 Bitmaps
常用命令
1.setbit key offset value 设置Bitmaps中某个偏移量的值
2.getbit key offset 获取Bitmaps中某个偏移量的值
3.bitcount key [start end] 统计字符串被设置为1的bit数量
4.bitop and/or destkey sourcekey1 sourcekey2…… 将多个bitmaps通过求交集/并集方式合并成一个新的bitmaps。
使用场景
-
活跃天数
-
打卡天数
-
登录天数
-
用户签到
-
统计活跃用户
-
统计用户是否在线
-
实现布隆过滤器
3.7 节 Geospatial
常用命令
1.geoadd key longitude latitude member 用于存储指定的地理空间位置
2.geopos key member [member ……] 从给定的 key 里返回所有指定名称(member)的位置(经度和纬度)
3.geodist key member1 member2 [m|km|ft|mi] 用于返回两个给定位置之间的距离。
4.georadius key longitude latitude radius m|km|ft|mi 以给定的经纬度(longitude latitude)为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离(radius )的所有位置元素。
使用场景
-
附近的电影院
-
附近的好友
-
离最近的火锅店
3.8 节 HyperLogLog
常用命令
1.pfadd key element1 element2…… 将所有元素参数添加到 Hyperloglog 数据结构中
2.pfcount key1 key2…… 计算Hyperloglog 近似基数,可以计算多个Hyperloglog ,统计基数总数
3.pfmerge destkey sourcekey1 sourcekey2…… 将一个或多个Hyperloglog(sourcekey1) 合并成一个 Hyperloglog (destkey )
使用场景
-
网站PV统计
-
网站UV统计
-
统计访问量(IP数)
-
统计在线用户数
-
统计每天搜索不同词条的个数
-
统计文章真实阅读数
第四章 Redis 事务
redsi的事务和关系型数据库事务解决问题不一样,原则也不一样,没有acid原则,redis事务保证命令按照队列顺序执行问题,所以redis事务分为两个阶段,第一个阶段是命令入队,第二个阶段是命令执行。
如果队列中命令都正确,那么按照入队顺序执行,如果队列中命令语法错误,队列所有命名都不执行,如果队列命令语法没错,但是执行失败,只有该命令本身不会执行,其他命令都会执行
redis事务命令
- multi 开启事务
- exec 执行事务
- discard 取消事务
第五章 Redis 主从复制
Redis集群模式分三种
-
主从模式
-
哨兵模式
-
集群模式
主从模式从一定程度上解决单机Redis的并发问题和可用性问题。但是主从模式问题很大,主节点挂了,需要手动将从节点切换为主节点,所以实际开发很少用到。然后Redis主从复制是哨兵机制和集群机制的根本,所以理解主从模式很重要。
主从复制可以分为3个阶段
-
连接建立阶段(即准备阶段)
-
数据同步阶段
-
命令传播阶段
主从模式原理如下:
-
从节点保存主节点(master)信息。
-
从节点(slave)内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与该节点建立网络连接。
-
从节点与主节点建立网络连接 。
-
发送ping命令 :连接建立成功后从节点发送 ping 请求进行首次通信
-
权限验证:如果主节点设置了 requirepass 参数,则需要密码验证,从节点必须配置 masterauth 参数保证与主节点相同的密码才能通过验证;如果验证失败复制将终止,从节点重新发起复制流程。
-
主从复制连接正常通信后,对于首次建立复制的场景,主节点会把持有的数据全部发送给从节点,这部分操作是耗时最长的步骤。
-
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。 redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
第六章 Redis 哨兵监控
哨兵模式主要解决主从复制master节点挂掉之后的,切换从节点为主节点问题,哨兵模式通过监控主从复制主节点和从节点完成自动切换主节点功能。
哨兵监控的原理:
1>监控阶段
-
sentinel(哨兵1)----->向master(主)和slave(从)发起info,拿到全信息。
-
sentinel(哨兵2)----->向master(主)发起info,就知道已经存在的sentinel(哨兵1)的信息,并且连接slave(从)。
-
sentinel(哨兵2)----->向sentinel(哨兵1)发起subscribe(订阅)。
2>通知阶段
sentinel不断的向master和slave发起通知,收集信息。
3>故障转移阶段
通知阶段sentinel发送的通知没得到master的回应,就会把master标记为SRI_S_DOWN,并且把master的状态发给各个sentinel,其他sentinel听到master挂了,也会向master发送通知,并把结果共享给各个sentinel,当有一半的sentinel都认为master挂了的时候,就会把master标记为SRI_0_DOWN。
4>投票阶段
方式: 自己最先接到哪个sentinel的竞选通知就会把票投给它
剔除一些情况:
-
不在线的
-
响应慢的
-
与原来master断开时间久的
-
优先级原则
第七章 Redis Cluster
集群模式至少需要6个redis服务器,集群模式就是n个主从复制模式,但是需要根据插槽机制分配每个节点存取数据范围。来解决单个主从redis不能存取数据过大问题,因为会降低从节点复制速度。
Redis集群的优点
-
Redis集群有多个master,可以减小访问瞬断问题的影响
-
Redis集群有多个master,可以提供更高的并发量
-
Redis集群可以分片存储,这样就可以存储更多的数据
Redis Cluster 原理
Redis Cluster将所有数据划分为16384个slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中。只有master节点会被分配槽位,slave节点不会分配槽位。
第八章 SpringDataRedis 连接集群
1.添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.编写配置
spring:
redis:
cluster:
nodes: 192.168.184.137:8001,192.168.184.137:8002,192.168.184.138:8001,192.168.184.138:8002,192.168.184.139:8001,192.168.184.139:800
3.编写测试
@SpringBootTest
class RedisDemo2ApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
redisTemplate.opsForValue().set("k6","v6");
System.out.println(redisTemplate.opsForValue().get("k6"));
}
}
第九章 Redis常见问题探析
1.Redis脑裂问题
Redis的集群脑裂是指因为网络问题,导致Redis Master节点跟Redis slave节点和Sentinel集群处于不同的网络分区,此时因为sentinel集群无法感知到master的存在,所以将slave节点提升为master节点。
解决方案:
redis.conf配置参数:
min-replicas-to-write 1
min-replicas-max-lag 5
//第一个参数表示最少的slave节点为1个
//第二个参数表示数据复制和同步的延迟不能超过5秒
2.Redis 缓存冷启动问题
冷启动是指服务器缓存中没有数据直接启动,访问量有比较大,mysql直接裸机运行。
解决方案:
通过缓存预热解决,通过storm实时计算出热点数据,然后定时将热点数据写入缓存。
3.Redis缓存穿透问题
查询一个redis和mysql肯定都不存在的数据是缓存穿透,例如查询id为-1的数据,多半为认为恶意攻击。
解决方案:
去数据库查不存在在redis存null,并且设置过期时间5分钟。
或者用布隆过滤器解决:布隆过滤器是一个bitMap数组,它说不存在的元素一定不存在,他说存在的未必存在。
4.Redis缓存击穿问题
某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,甚至可能打垮数据库。从造成问题的原因去解决,当热点Key失效的一刹那,大并发裸奔访问数据库,数据库被打垮。
解决方案:
我们只需要在热点Key失效的一刹那保证只有一个请求过来就可以了。这种需求肯定用锁解决,理论上可以用同步锁解决,但这个不靠谱,锁只能锁一个进程,但是微服务是多个服务是多个进程,根本不起作用。所以用分布式锁解决。
5.Redis缓存雪崩问题
大量缓存同时失效,数据库被击垮问题。
解决方案:
用二级缓存解决:先查询本地nginx缓存查询有没有数据,有数据,直接返回;nginx缓存没有数据再去redis分布式缓存查询,如果有将redis缓存同步nginx缓存在返回;如果redis没有,取数据库查询,数据库存在将数据同步到redis并返回。只要nginx的过期时间和redis的过期时间不一样就解决了缓存雪崩问题,并合理使用了本地缓存和分布式缓存。
6.Redis 开发规范
key设计技巧
-
把表名转换为key前缀,如 tag:
-
把第二段放置用于区分key的字段,对应msyql中主键的列名,如 user_id
-
第三段放置主键值,如 2,3,4
-
第四段写存储的列名
value设计
拒绝bigkey,防止网卡流量、慢查询,string类型控制在10KB以内,hash、 list、set、zset元素个数不要超过5000。
7.Redis 数据一致性问题
三种更新策略
-
先更新数据库,再更新缓存
-
先删除缓存,再更新数据库
-
先更新数据库,再删除缓存
由于1、2都会导致脏数据,所以不考虑。