【Redis】开启掘金成长之旅从Redis开始

158 阅读6分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天(点击查看活动详情)

作为开发的程序员对Redis都应该不陌生,Redis是一个Key-Value键值对数据库,也是一个nosql数据库。 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 有了它可以帮助我们提高系统性能。

所以接下来我将从以下几点来写Redis。

Redis.png

Redis应用场景

  1. 可以在电商业务系统中用作秒杀库存扣减。
  2. 可以用来做分布式锁。
  3. 可以用作缓存,比如App首页的访问数据,缓存一些不经常变的数据。
  4. 可以执行lua脚本。
  5. 可以实现百万key模糊查找。
  6. 还可以实现手机验证码场景。

Redis基础知识点

Redis数据结构有哪些?

  • Redis的5种基本数据结构:String.Hash,List, Set, Sor tedSet
  • 其他数据结构:HyperLogLog.Geo.Pub/Sub
  • 用于防止缓存穿透的数据结构:Redis Module,像BloomFiiterRedisSearch,Redis-ML设置key值过期:setRedis(Key.valuetime+Mathrandom*10000);

Redis的keys命令

Redis的单线程的。

keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复 scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长 SMEMBERS 命令可以返回集合健当前包含的所有元素 SCAN 这类增量式迭代命令来说,在对键进行增量式迭代的过程中,键可能会被修改,所以增量式选代命令只能对被返回的元素提供有限的保证。

Redis分布式锁实现方式

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放 如果在setnx之后执行expire之前进程意外crash或者要重启维护,把setnx和expire合成一条指令来用的

Redis异步队列

  • list结构作为队列,rpush生产消息,Ipop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
  • list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来
  • pub/sub主题订阅者模式,可以实现1N的消息队列,实现生产一次,消费多次
  • pub/sub主题订阅者模式,消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如RocketMQ

Redis延时队列

sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。

Redis持久化

RDB做镜像全量持久化,AOF做增量持久化,因为RDB会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要AOF来配合使用。在redis实例重启时,会使用RDB持久化文件重新构建内存,再使用AOF重放近期的操作指令来实现完整恢复重启之前的状态。 Redis本身的机制是AOF持久化开启且存在AOF文件时,优先加载AOF文件;AOF关闭或者AOF文件不存在时,加载RDB文件;加载AOF/RDB文件城后,Redis启动成功;AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。

机器断电对数据丢失的影响

AOF日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据,但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。

Redis集群的同步机制

Redis可以使用主从同步,从从同步 第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点 复制节点接受完成后将RDB镜像加载到内存,加载完成后,再通知主节点 后续的增量数据通过AOF日志同步即可,有点类似数据库的binlog

Redis 集群的高可用

Redis Sentinal 着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。 Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

Redis缓存雪崩

大面积的缓存失效,打崩了数据库,同一时间大面积失效,那一瞬间Redis跟没有一样,那这个数量级别的请求直接打到数据库几乎是灾难性的,你想想如果打挂的是一个用户服务的库,那其他依赖他的库所有的接口几乎都会报错,如果没做熔断等策略基本上就是瞬间挂一片的节奏。

解决办法:

  • 批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效
  • Redis是集群部署,将热点数据均匀分布在不同的Redis库中也能避免全部失效的问题
  • 设置热点数据永远不过期,有更新操作就更新缓存就好了

Redis缓存击穿

一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。

解决办法:

1、设置热点数据永不过期。 2、增加互斥锁。

Redis缓存穿透

用户不断的发起缓存和数据库中均不存在的数据的请求,导致数据库压力过大,严重会击垮数据库

解决办法:

  • 增加参数校验
  • 从网关层Nginx增加配置项,对单个IP每秒访问次数超出阈值的IP都拉黑。
  • 布降过滤器(Bloom Filter)这个也能很好的防止缓存穿透的发生,他的原理也很简单就是利用高效的数据结构和算法快速判断出你这个Kev是否在数据库中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。