Redis:实战问题

Jedis

连接
  • sentinel:直接连sentinel,通过sentinel获取master的地址然后封装成连接
  • cluster:缓存了slot到node的映射关系,调用的时候根据映射关系获取对应的connectPool(pool在这里其实就代表对应node的连接)
Pipeline

缓存命令,然后批量(按配置默认8192)发送给服务端,节省多次请求/响应的开销。
发送和返回都会存储到对应的缓冲区。

分布式锁

分布式锁:互斥、避免死锁、我只能释放我加的锁

  • 加锁:set key value(reqId) notExist setWithExpire time
  • 释放锁:通过value判断,只能释放自己加的锁,避免超时出现乱释放的情况

红锁:分布式集群锁,避免单点问题,纷纷加锁,大部分加锁成功算成功

Redission:基于redis实现了一种分布式服务

  • 分布式锁:用hash机构实现,key是线程名,value是重入次数

缓存时的数据一致性问题

缓存需要设置过期时间,这样能保证最终是一致的。
数据有变化时,需要对Redis和数据库同时操作,为了尽量保证数据一致,我们需要考虑以下问题

操作Redis是更新还是删除

删除Redis中的数据,毕竟最终还是以数据库为主

先操作Redis还是先操作数据库
  • 先数据库后Redis:删除redis失败,redis是旧值(可以考虑失败时重新删除:比如发消息重试;监听数据库binlog)
  • 先Redis后数据库:更新数据库成功,但是更新前,redis删除后,其他线程来缓存了旧值,数据还是不一致
  • 先删除Redis 然后数据库 延时 再删除Redis:还是会有问题,类似上一步,再最后的删除步骤失败了,还是不一致,只不过概率会变低

热点数据发现

  • redis-faina 监听redis服务端(只能单点监控)
  • 抓包

缓存雪崩

大量热点key同时过期,请求量一下都打到数据库,导致数据库瞬时压力很高

解决办法:

  • 过期时间加随机数
  • 永不过期(数据不变化)
  • 缓存预更新,后台起线程定时扫描缓存,预更新过期的缓存

缓存穿透

请求key不存在,大量请求一直请求到数据库

解决办法:

  • 缓存空对象
  • 布隆过滤器(引入了误判率):假如过滤器认为元素不存在,则一定不存在,认为存在,有可能不存在。布隆过滤器的数据是离线加载进去的,添加数据方便,但是删除数据很麻烦。

缓存击穿

大量请求打到一个key上,key失效时导致大量请求打到数据库

解决办法:

  • 使用分布式锁,当发现缓存为空时加锁,只有第一个请求打到数据库,其余都走缓存
posted @ 2020-07-18 17:09  挣扎一下  阅读(203)  评论(0编辑  收藏  举报