redis是什么?简述它的优缺点?
定义
redis本质上是一个key-value类型的内存数据库,很像memcached,整个数据库加载在内存当中操作,定期通过异步操作把数据库中的数据flush到硬盘上进行保存。
因为是纯内存操作,redis的性能非常出色,每秒可以处理超过10万次读写操作,是已知性能最快的key-value数据库。
优点
- 读写性能极高
- 支持多种数据结构
- 支持持久化
- 支持事务
- 支持主从复制
- 丰富的特性 - Redis还支持publish/subscribe,通知,key过期等特性
缺点
- 容易受物理内存的限制,不能做海量数据的读写
- 主机宕机,宕机前有部分数据未能同步到从机,切换ip后还会引入数据不一致的问题,降低了系统的可用性
6_redis 常见的使用场景
- 缓存, 各种数据结构都可以
- 计数器, String 自增自减,譬如粉丝,点赞
- 分布式锁, String SETNX命令
- 消息系统, List
- 最新列表, List
- 共同好有,SET
- 排行榜, ZSET
7_redis 的数据类型有哪些
- String, 做简单的键值对缓存,做计数器
- Hash, 缓存结构化的数据譬如对象
- Set, 可以做交集、并集、差集,可以用来两个人的粉丝列表交集
- List, 存储一些列表型数据结构
- SortedSet,排序,排行榜
- Bitmap
- Hyperloglog
- Geospatial
redis 持久化机制
-
快照RDB: 在指定的时间间隔内将内存中的数据集快照写入磁盘,它恢复时是将快照文件直接读到内存里。
- 优势: 适合大规模的数据恢复,因为恢复速度较快
- 劣势:不能保证数据的完整性,因为在一定间隔时间做一次备份,所以如果redis意外挂掉的话,就会丢失最后一次快照后的所有修改。
-
只追加文件AOF:(append only file)采用日志的形式来记录每个写操作,追加到文件中,重启时再重新执行AOF文件中的命令来恢复数据。它主要解决数据持久化的实时性问题。默认是不开启的。
- 优势:数据的一致性和完整性更高
- 劣势:AOF记录的内容越多,文件越大,数据恢复变慢。
-
混合模式: aof文件,前半段是BDB格式的全量数据后半段是AOF格式的增量数据
- 优势:混合持久化结合了RDB持久化 和AOF持久化的优点, 由于绝大部分都是RDB格式,加载速度快,同时结合AOF,增量的数据以AOF方式保存了,数据更少的丢失。
- 劣势:兼容性差,一旦开启了混合持久化,在4.0之前版本都不识别该aof文件,同时由于前部分是RDB格式,阅读性较差。
redis 主从模式、哨兵(sentinel) 配置、cluster(集群)联系与区别
主从模式
Redis部署了多台机器,有主节点,负责读写操作,有从节点,只负责读操作。从节点的数据来自主节点,实现原理就是主从复制机制
- 优点: 主从复制,读写分离,高可用
- 缺点: 一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址
哨兵模式
哨兵模式的核心还是主从复制。只不过相对于主从模式在主节点宕机导致不可写的情况下,多了一个竞选机制——从所有的从节点竞选出新的主节点。竞选机制的实现,是依赖于在系统中启动一个sentinel进程
- 优缺点:哨兵模式基于主从模式,实现读写分离,它还可以自动切换,系统可用性更高。但是它每个节点存储的数据是一样的,浪费内存,并且不好在线扩容。
Cluster集群模式
https://blog.csdn.net/weixin_40205234/article/details/124614720
下次再看
redis 过期数据的删除策略
Redis 的过期删除策略是:惰性删除和定期删除两种策略配合使用
redis 内存淘汰策略
- noeviction(默认策略):禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错(DEL请求和部分特殊请求除外)
- allkeys-lru:从所有key中使用LRU算法进行淘汰(LRU算法:即最近最少使用算法)
- volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰
- allkeys-random:从所有key中随机淘汰数据
- volatile-random:从设置了过期时间的key中随机淘汰
- volatile-ttl:在设置了过期时间的key中,淘汰过期时间剩余最短的
- allkeys-lfu:
- volatile-lfu:
如何保证缓存与数据库双写时的数据一致性
先更新,后删除
缓存雪崩
现象
如果缓在某一个时刻出现大规模的key失效,那么就会导致大量的请求打在了数据库上面,导致数据库压 力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机,这就是缓存雪崩。
原因
造成缓存雪崩的关键在于同一时间的大规模的key失效,主要有两种可能:第一种是Redis宕机,第二种 可能就是采用了相同的过期时间。
解决方案
-
均匀过期: 设置不同的过期时间,让缓存失效的时间尽量均匀
-
分级缓存: 第一级缓存失效的基础上,访问二级缓存,每一级缓存的失效时间都不同。
-
永不过期: 热点数据缓存永远不过期
-
保证Redis服务器的高可用性,防止Redis宕机。可以使用主从+哨兵,Redis集群来避免全盘崩盘
-
互斥锁: 在缓存失效后,通过互斥锁或者队列来控制读数据写缓存的线程数量
-
使用熔断机制: 限流降级。当流量达到一定的阈值,直接返回系统拥挤之类的示
-
开启Redis持久化机制,尽快恢复缓存数据
缓存击穿
缓存击穿跟缓存雪崩有点类似,缓存雪崩是大规模的key失效,而缓存击穿是某个热点的key失效,大并发集中对其进行请求,就会造成大量请求读缓存没读到数据,从而导致高并发访问数据库,引起数据库压力剧增。这种现象就叫做缓存击穿。
从两个方面解决,第一是否可以考虑热点key不设置过期时间,第二是否可以考虑降低打在数据库上的请求数量。
缓存穿透
缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请
求该数据都要去数据库中查询一遍。如果有恶意攻击者不断请求系统中不存在的数据,会导致短时间大
量请求落在数据库上,造成数据库压力过大,甚至导致数据库承受不住而宕机崩溃。
解决方案
- 将无效的key存放进redis中
- 使用不隆过滤器
将数据库中的所有key都存储在布隆过滤器中,在查询redis前先去布隆过滤器查询key是否存在,如果不存在就直接返回,不让其访问数据库
什么是分布式锁,为什么使用分布式锁
锁在程序中的作用就是同步工具,保证共享资源在同一时刻只能被一个线程访问,java中的锁我们都很 熟悉了,像synchronized、lock都是我们经常使用的,但是java的锁只能保证单机的时候有效,分布式 集群环境就无能为力了,这个时候我们就需要用到分布式锁。
分布式锁,顾名思义,就是分布式项目开发中用到的锁,可以用来控制分布式系统之间同步访问共享资
源。
一般来说,分布式锁需要满足的特性有这么几点:
- 互斥性
- 高可用性
- 防止锁超时
- 独占性
redis 分布式锁的实现
setnx key value 加锁,当返回为1表示获取到锁, 当返回为0表示锁被占用
del key 解锁
如果一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,这块资源将
会永远被锁住,别的线程别想进来
expire 设置过期时间
遇到的问题
- SETNX 和 EXPIRE 非原子性
- 锁误解除
- 超时解锁导致并发
- 不可重入
- 无法等待锁释放