redis-review

193 阅读6分钟

redis是什么?简述它的优缺点?

定义

redis本质上是一个key-value类型的内存数据库,很像memcached,整个数据库加载在内存当中操作,定期通过异步操作把数据库中的数据flush到硬盘上进行保存。 因为是纯内存操作,redis的性能非常出色,每秒可以处理超过10万次读写操作,是已知性能最快的key-value数据库。

优点

  1. 读写性能极高
  2. 支持多种数据结构
  3. 支持持久化
  4. 支持事务
  5. 支持主从复制
  6. 丰富的特性 - Redis还支持publish/subscribe,通知,key过期等特性

缺点

  1. 容易受物理内存的限制,不能做海量数据的读写
  2. 主机宕机,宕机前有部分数据未能同步到从机,切换ip后还会引入数据不一致的问题,降低了系统的可用性

6_redis 常见的使用场景

  1. 缓存, 各种数据结构都可以
  2. 计数器, String 自增自减,譬如粉丝,点赞
  3. 分布式锁, String SETNX命令
  4. 消息系统, List
  5. 最新列表, List
  6. 共同好有,SET
  7. 排行榜, ZSET

7_redis 的数据类型有哪些

  1. String, 做简单的键值对缓存,做计数器
  2. Hash, 缓存结构化的数据譬如对象
  3. Set, 可以做交集、并集、差集,可以用来两个人的粉丝列表交集
  4. List, 存储一些列表型数据结构
  5. SortedSet,排序,排行榜
  6. Bitmap
  7. Hyperloglog
  8. Geospatial

redis 持久化机制

RDB AOF 混合模式

redis 过期数据的删除策略

Redis 的过期删除策略是:惰性删除和定期删除两种策略配合使用

redis 内存淘汰策略

  1. noeviction(默认策略):禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错(DEL请求和部分特殊请求除外)
  2. allkeys-lru:从所有key中使用LRU算法进行淘汰(LRU算法:即最近最少使用算法)
  3. volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰
  4. allkeys-random:从所有key中随机淘汰数据
  5. volatile-random:从设置了过期时间的key中随机淘汰
  6. volatile-ttl:在设置了过期时间的key中,淘汰过期时间剩余最短的
  7. allkeys-lfu:
  8. volatile-lfu:

如何保证缓存与数据库双写时的数据一致性

先更新,后删除

缓存雪崩

现象

如果缓在某一个时刻出现大规模的key失效,那么就会导致大量的请求打在了数据库上面,导致数据库压 力巨大,如果在高并发的情况下,可能瞬间就会导致数据库宕机,这就是缓存雪崩。

原因

造成缓存雪崩的关键在于同一时间的大规模的key失效,主要有两种可能:第一种是Redis宕机,第二种 可能就是采用了相同的过期时间。

解决方案

  • 均匀过期: 设置不同的过期时间,让缓存失效的时间尽量均匀

  • 分级缓存: 第一级缓存失效的基础上,访问二级缓存,每一级缓存的失效时间都不同。

  • 永不过期: 热点数据缓存永远不过期

  • 保证Redis服务器的高可用性,防止Redis宕机。可以使用主从+哨兵,Redis集群来避免全盘崩盘

  • 互斥锁: 在缓存失效后,通过互斥锁或者队列来控制读数据写缓存的线程数量

  • 使用熔断机制: 限流降级。当流量达到一定的阈值,直接返回􏰾系统拥挤􏱀之类的􏰒示

  • 开启Redis持久化机制,尽快恢复缓存数据

缓存击穿

缓存击穿跟缓存雪崩有点类似,缓存雪崩是大规模的key失效,而缓存击穿是某个热点的key失效,大并发集中对其进行请求,就会造成大量请求读缓存没读到数据,从而导致高并发访问数据库,引起数据库压力剧增。这种现象就叫做缓存击穿。 从两个方面解决,第一是否可以考虑热点key不设置过期时间,第二是否可以考虑降低打在数据库上的请求数量。

缓存穿透

缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请 求该数据都要去数据库中查询一遍。如果有恶意攻击者不断请求系统中不存在的数据,会导致短时间大 量请求落在数据库上,造成数据库压力过大,甚至导致数据库承受不住而宕机崩溃。

解决方案

  • 将无效的key存放进redis中
  • 使用不隆过滤器

将数据库中的所有key都存储在布隆过滤器中,在查询redis前先去布隆过滤器查询key是否存在,如果不存在就直接返回,不让其访问数据库

什么是分布式锁,为什么使用分布式锁

锁在程序中的作用就是同步工具,保证共享资源在同一时刻只能被一个线程访问,java中的锁我们都很 熟悉了,像synchronized、lock都是我们经常使用的,但是java的锁只能保证单机的时候有效,分布式 集群环境就无能为力了,这个时候我们就需要用到分布式锁。 分布式锁,顾名思义,就是分布式项目开发中用到的锁,可以用来控制分布式系统之间同步访问共享资 源。

一般来说,分布式锁需要满足的特性有这么几点:

  1. 互斥性
  2. 高可用性
  3. 防止锁超时
  4. 独占性

redis 分布式锁的实现

setnx key value 加锁,当返回为1表示获取到锁, 当返回为0表示锁被占用

del key 解锁

如果一个得到锁的线程在执行任务的过程中挂掉,来不及显式地释放锁,这块资源将 会永远被锁住,别的线程别想进来

expire 设置过期时间

遇到的问题

  1. SETNX 和 EXPIRE 非原子性
  2. 锁误解除
  3. 超时解锁导致并发
  4. 不可重入
  5. 无法等待锁释放