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 AOF 混合模式
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 非原子性
- 锁误解除
- 超时解锁导致并发
- 不可重入
- 无法等待锁释放