优点:
速度快,效率高: 基于内存的操作,单线程多CPU,没有线程上下文切换,采用单线程-多路复用IO模型
持久化: 支持AOF和RDB两种持久化方式
支持主从复制: 主机会自动将数据同步到从机,可以进行读写分离。
数据类型丰富: 除了支持string类型的value外还支持string、hash、set、sortedset、list等数据结构。
缺点:数据不一致
主从同步,如果主机宕机,宕机前有一部分数据没有同步到从机,会导致数据不一致。
q全量复制:当数据量较大时,会对主从节点和网络造成很大的开销
Redis与其他缓存组件的区别
redis:有部份存在硬盘上,这样能保证数据的持久性,支持数据的持久化,数据支持类型多
memcache:数据全部存在内存之中,数据类型单一
MongoDB :适合大数据量的存储,依赖VM系统做内存管理,吃内存也比较厉害
Redis 为什么采用单线程?
Redis 单线程为什么还能这么快?
Redis 单线程如何处理那么多的并发客户端连接?
Redis 为什么不合适当数据库来,只适合用来做缓存?
String、List、Hash、Set、zset(有序集合)
所有的数据结构都是以唯一的 key字符串作为名称,然后通过这个唯一 key 值来获取相应的 value 数据。
Redis5.0 增加了一个数据结构 Stream,它是一个新的强大的支持多播的可持久化的消息队列
String(字符串):
list(列表):
hash:
set(集合)
zset(有序列表)
通用规则
list/set/hash/zset 这四种数据结构是容器型数据结构,共享下面两条通用规则
过期时间
Redis 所有的数据结构都可以设置过期时间,时间到了,Redis 会自动删除相应的对象
注意:如果一个字符串已经设置了过期时间,然后你调用了set 方法修改了它,它的过期时间会消失
redis提供两种方式进行持久化,
AOF有3种同步策略:每秒同步、每修改同步和不同步
RDB 和AOF 优缺点:
AOF文件的体积过大的解决办法:redis引入了AOF重写机制压缩文件
AOF 重写(bgrewriteaof ):
自动执行
BGREWRITEAOF场景:
集群参考
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
同步分为:全量同步和增量同步
全量同步:
增量同步:
全量复制:
主从复制特点:
哨兵任务:监控(Monitoring)、提醒(Notification)、自动故障迁移
高可用原理
1.三个定时监控任务
2.主观下线:哨兵节点ping不通从节点,直接判定失败
3.客观下线:哨兵节点ping不通主节点,向其他哨兵节点咨询,过半直接判定失败
4.领导者哨兵节点选举:当主节点下线,哨兵节点向其他哨兵节点发送请求成为领导者命令,投票过半称为领导者。然后选出主节点
5.故障转移:选一个优先级最高、复制偏移量最大、id最小的从节点作为主节点;然后在哨兵节点集合中更新主节点
哨兵选举: 因为只能有一个sentinel节点去完成故障转移
主节点的选取规则如下:
挑选出需要继任的slaver后,领头哨兵向该数据库发送命令使其升格为master,然后再向其他slave发送命令接受新的master,最后更新数据。将已经停止的旧的master更新为新的master的从数据库,使其恢复服务后以slave的身份继续运行。
消息丢失:
特点:无中心结构、使用数据分片引入哈希槽
容错:
网络抖动:
redis 内存数据集大小上升到一定大小的时候,Redis 会根据自身数据淘汰策略,加载热数据到内存。
redis 提供 6种数据淘汰策略:
----------->>>>>>>>>>>>>>>>>上3种已设置过期时间<<<<<<<<<<-----------------------------------------
redis事务是通过MULTI,EXEC,DISCARD和WATCH四个原语实现的。
redis事务分别是 multi/exec/discard。
Redis 的事务根本不能算「原子性」,而仅仅是满足了事务的「隔离性」,隔离性中的串行化——当前执行的事务有着不被其它事务打断的权利。
watch 机制
Redis 提供了这种 watch 的机制,它就是一种乐观锁**(CAS)**
watch 会在事务开始之前盯住 1 个或多个关键变量,当事务执行时,也就是服务器收到了 exec 指令要顺序执行缓存的事务队列时,Redis 会检查关键变量自 watch 之后,是否被修改了 (包括当前事务所在的客户端)。如果关键变量被人动过了,exec 指令就会返回 null回复告知客户端事务执行失败,这个时候客户端一般会选择重试。
**注意事项:**Redis 禁止在 multi 和 exec 之间执行 watch 指令,而必须在 multi 之前做好盯住关键变量,否则会出错。
为什么Redis不支持回滚
RESP 是 Redis 序列化协议的简写。它是一种直观的文本协议,优势在于实现异常简单,解析性能极好
Redis 协议将传输的结构数据分为 5 种最小单元类型,单元结束时统一加上回车换行符号\r\n。
1、单行字符串 以 + 符号开头。
2、多行字符串 以 $ 符号开头,后跟字符串长度。
3、整数值 以 : 符号开头,后跟整数的字符串形式。
4、错误消息 以 - 符号开头。
5、数组 以 * 号开头,后跟数组的长度。
单行字符串 hello world +hello world\r\n
多行字符串 hello world $11\r\nhello world\r\n 多行字符串当然也可以表示单行字符串。
整数 1024 :1024\r\n
错误 参数类型错误 -WRONGTYPE Operation against a key holding the wrong kind of value
数组 [1,2,3] *3\r\n:1\r\n:2\r\n:3\r\n
NULL 用多行字符串表示,不过长度要写成-1。 $-1\r\n
空串 用多行字符串表示,长度填 0。 $0\r\n\r\n
使用redis过程中,通常会这样做:先读取缓存,如果缓存不存在,则读取数据库,插入缓存
场景1:
解决方案:
场景2:
解决方案:
问题描述:
解决方案:
问题产生的原因
危害:
如何发现热点数据
解决方法:
方案1: 解决缓存失效引起的问题
使用互斥锁(mutex key),单机用synchronized,lock等,分布式用分布式锁。"提前"使用互斥锁
缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。
在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作。
方案2: key访问量过大引起
阿里云数据库解热点之道:读写分离方案
此方案优点:
缓存穿透:
缓存雪崩:
缓存击穿:
布隆过滤器的巨大用处就是,能够迅速判断一个元素是否在一个集合中
三个使用场景:
布隆过滤器可以理解为一个不怎么精确的 set 结构,当你使用它的 contains 方法判断某个对象是否存在时,它可能会误判
原理
基本指令:
经常会被查询,但是不经常被修改或者删除的数据,特别适合将运行结果放入缓存,内存的读写速度远快于硬盘
什么数据可以放缓存
这类数据包括比如涉及到钱、密钥、业务关键性核心数据等不能放入缓存
使用hash
zset,命令:zadd
统计点击数
list,命令lpush
一般是使用 setnx 指令获取锁、del 指令释放锁
set成功表示获取锁,set失败表示获取失败,失败后需要重试。
问题:
分布式全局唯一ID的生成方法
1、简单限流
2、漏斗限流
用于数据量上亿的场景下,例如几亿用户系统的签到,去重登录次数统计,某用户是否在线状态等等。
Redis 提供了位图数据结构,使用setbit、getbit、bitcount命令。
原理是:redis内构建一个足够长的数组,每个数组元素只能是0和1两个值,数组下标index表示上面例子的用户id(必须是数字哈)
问题:
PubSub模块
Stream : 参考了kafka的设计方式进行分组
Redis 在 2.8.9 版本添加了 HyperLogLog 结构。
HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
HyperLogLog :
redis与spring的整合一般分为spring-data-redis整合和jedis整合,
StringRedisTemplate和RedisTemplate区别
StringRedisTemplate继承RedisTemplate。
两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。
StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的
RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
使用时注意事项: