【Redis系列一】

Redis基础

缓存雪崩、击穿、穿透

Redis哨兵、持久化、主从、手撕LRU

Redis终章_凛冬将至 FPX_新王登基

Redis常见面试题

Redis秒杀

Redis基础

Redis简介

Redis 是一个基于内存的高性能key-value数据库。

Redis的整个数据库统统加载在内存当中进行操作,所以性能非常出色,每秒可以处理超过 10万次读写操作。

Redis的出色之处不仅仅是性能,Redis是支持保存多种数据结构,此外单个value的最大限制是1GB,因此Redis可以用来实现很多有用的功能。

Redis拥有持久化机制,通过持久化机制把内存中的数据同步到硬盘文件中保证数据持久化;当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。

Redis是高并发系统中重要的分布式缓存中间件,主要用来解决高并发下分担DB资源的负载,从而提升系统吞吐量。

Redis为什么快

纯内存操作:内存操作ns级别,而硬盘寻址时间ms级别。

数据结构简单,对数据操作也简单;(不使用表,不会进行数据关联)

单线程操作,避免了频繁的上下文切换

采用了非阻塞 I/O 多路复用机制

Redis数据类型

String
最常规的set/get操作,value可以是String也可以是数字。可以通过decr\incr等操作做计数功能的缓存。

Hash
这里value存放的是结构化的对象,使用hset方便地操作其中的一个字段。同时可以通过hgetall操作来获取整个对象数据。

list
使用List的数据结构,可以很好的完成排队,先进先出的原则,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能。
set
因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。

sorted set
sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作

深度图解Redis Cluster原理

深度图解Redis Cluster原理

单机
主从 一个master 多个replication
哨兵 基于主从,增加几个哨兵,只监控不放数据
cluster模式 奇数个master,每个master任意个slave

一致性哈希算法

避免缓存失效雪崩

一致性哈希算法 虚拟节点

Redis持久化

Redis持久化有两种方式:RDB和AOF。

RDB:定时镜像全量持久化
RDB是Redis默认的持久化方式。按照一定的时间策略把内存以快照的形式保存到硬盘的二进制文件中。是一种Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件的save参数来定义快照的周期。
RDB原理:fork和cow
fork是指redis通过创建子进程来进行RDB操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。

AOF
Redis会将每个收到的写命令通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

优缺点对比
1.RDB方式不能保证数据的高可用,redis在定时持久化前宕机,此前所有未备份数据会丢失。
2.RDB方式通过fork子进程进行数据持久化,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务。
3.RDB数据恢复效率要高于AOF
4.AOF文件会不断增大,AOF文件过大会影响Redis重启的恢复速度。
5.两种持久化同时开启时,数据恢复会优先选择AOF。

Redis同步机制 先RDB+增量数据通过AOF

在这里插入图片描述

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

Redis集群,集群的高可用怎么保证,集群的原理是什么?

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

Redis常见应用场景

1、热点数据的缓存

由于redis访问速度块、支持的数据类型比较丰富,所以redis很适合用来存储热点数据,另外结合expire,我们可以设置过期时间然后再进行缓存更新操作,这个功能最为常见。

2、限时业务的运用

redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。

3、计数器相关问题

redis由于incrby命令可以实现原子性的递增,所以可以运用于高并发的秒杀活动、分布式序列号的生成、具体业务还体现在比如限制一个手机号发多少条短信、一个接口一分钟限制多少请求、一个接口一天限制调用多少次等等。

4、排行榜相关问题

关系型数据库在排行榜方面查询速度普遍偏慢,所以可以借助redis的SortedSet进行热点数据的排序。

5、分布式锁

这个主要利用redis的setnx命令进行,setnx:"set if not exists"就是如果不存在则成功设置缓存同时返回1,否则返回0 。服务器是集群部署时,定时任务可能在两台机器上都会运行,所以在定时任务中首先 通过setnx设置一个lock,如果成功设置则执行,如果没有成功设置,则表明该定时任务已执行。 当然结合具体业务,我们可以给这个lock加一个过期时间,防止死锁。

6、延时操作(发布/订阅)

场景举例:在订单生产后我们占用了库存,10分钟后去检验用户是够真正购买,如果没有购买将该单据设置无效,同时还原库存。 由于redis自2.8.0之后版本提供Keyspace Notifications功能,允许客户订阅Pub/Sub频道,以便以某种方式接收影响Redis数据集的事件。 所以我们对于上面的需求就可以用以下解决方案,我们在订单生产时,设置一个key,同时设置10分钟后过期, 我们在后台实现一个监听器,监听key的实效,监听到key失效时将后续逻辑加上。 当然我们也可以利用rabbitmq、activemq等消息中间件的延迟队列服务实现该需求。

7、分页

redis的set集合中提供了一个zrangebylex方法,语法如下:

ZRANGEBYLEX key min max [LIMIT offset count]

通过ZRANGEBYLEX zset - + LIMIT 0 10 可以进行分页数据查询,其中- +表示获取全部数据

8、点赞、好友等相互关系的存储

Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。 又或者在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。

利用set存储用户之间的点赞关联,可以在点赞前判断是否点赞过就利用了sismember方法,当时这个接口的响应时间控制在10毫秒内,十分高效。

9、队列

由于redis有list push和list pop这样的命令,所以能够很方便的执行队列操作。

Redis常见问题

1.缓存和数据库双写一致性问题

分析:一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。

前提:如果对数据有强一致性要求,不能放缓存。我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,只能说降低不一致发生的概率,无法完全避免。因此,有强一致性要求的数据,不能放缓存。

首先,采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。

2.缓存预热

缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!

实现思路:
直接写个缓存刷新页面,上线时手工操作下;
数据量不大,可以在项目启动的时候自动进行加载;
定时刷新缓存

3.缓存雪崩 缓存穿透

缓存雪崩: 即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。

解决:
① 给缓存的失效时间,加上一个随机值,避免集体失效。
② 使用互斥锁,但是该方案吞吐量明显下降了。
③设置热点数据永远不过期

缓存穿透: 即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。

解决:
① 利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试
②采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。
③接口层增加校验,比如用户鉴权校验,参数做校验,不合法的参数直接代码Return,比如:id 做基础校验,id <=0的直接拦截等
③提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。

大并发场景时需要考虑这两中问题。

附–布隆过滤器
布隆过滤器

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

设置热点数据永远不过期。或者加上互斥锁

4.缓存的并发竞争问题

同时有多个子系统去set一个key。

① 如果对这个key操作,不要求顺序
这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可,比较简单。
② 如果对这个key操作,要求顺序
假设有一个key1,系统A需要将key1设置为valueA,系统B需要将key1设置为valueB,系统C需要将key1设置为valueC.
期望按照key1的value值按照 valueA–>valueB–>valueC的顺序变化。这种时候我们在数据写入数据库的时候,需要保存一个时间戳。假设时间戳如下

系统A key 1 {valueA 3:00}
系统B key 1 {valueB 3:05}
系统C key 1 {valueC 3:10}
那么,假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现自己的valueA的时间戳早于缓存中的时间戳,那就不做set操作了。以此类推。

其他方法,比如利用队列,将set方法变成串行访问也可以。

5.Redis的过期策略和内存淘汰机制 LRU

redis采用的是定期删除+惰性删除策略

定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。

于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。

采用定期删除+惰性删除就没其他问题了么?
不是的,如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。redis中存在一个配置属性stop-writes-on-bgsave-error,默认为yes。当bgsave保存失败后,停止接收写操作。此时就应该采用内存淘汰机制。
在redis.conf中有一行配置

# maxmemory-policy volatile-lru

如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效,此时就应该采用内存淘汰机制LRU

内存淘汰策略 (maxmemory-policy)
1)no-eviction:当内存不足以容纳新写入数据时,新写入操作会报错。不推荐

2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用,目前项目在用这种。

3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。不推荐

4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。这种情况一般是把redis既当缓存,又做持久化存储的时候才用。不推荐

5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。依然不推荐

6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。不推荐

ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 no-eviction(不删除) 基本上一致。

自己LRU代码

Jedis常见错误解决

Jedis异常分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值