什么是Redis?
其实Redis本质上就是一个使用C语言开发的数据库,不过与传统Mysql数据库不同的是Redis的数据是直接存在内存中的(内存数据库)所以他的读取速度相当快!
Redis用来干嘛的?
Redis众所周知的主要是用来做缓存,消息队列,分布式锁;
为什么需要缓存?缓存的作用是什么?缓存的流程是怎样的?
在我们的业务场景的时候,主要是面对的高性能、高并发的业务!
缓存的流程:1.首先用户请求的数据看看是否存在于缓存当中(如果是则直接返回对应数据)2.如果没有在缓存中,就会就数据库中查找,如果存在就会去更新缓存,返回数据 3.如果数据库中没有对应的数据则返回空数据;
![](https://i-blog.csdnimg.cn/blog_migrate/3177c7b0943d27ac69638d228e601765.png)
用户第一次访问数据库中的数据的话,那肯定相对较慢,因为需要从硬盘中读取数据
用户如果访问高频数据的话,可以将数据存在缓存中,从内存中读取的速度肯定快上许多
所以我们常常需要注意的是要保持数据库与缓存中的数据一致性!
Redis的常见数据结构与使用场景分析
1.String
字符串:应用场景一般是应用在需要计数的场景,比如说用户的访问次数,热点文章的点赞
2.List
链表:应用场景一般是在发布于订阅或者是说消息队列、慢查询
3.Set
无序集合:场景一般是应用于需要存放的数据不能重复和需要获取多个数据源交集与并集的情况
4.Sort Set
有序集合:应用场景一般是需要对数据根据某个权重进行排序的情况,比如说在直播时礼物排行榜
5.Hash
哈希:应用场景一般是用于对象数据的存储,比如说商品信息,用户信息等
6.BitMap
位图:应用场景可以是统计用户的在线次数,记录用户行为,同时多个bitmap布隆过滤器也是可以
Redis单线程模型详解
1.既然是单线程,那如何去监听大量的客户端连接呢?
都说Redis是用过IO多路复用程序来监听来自客户端的多个连接,他会将感兴趣的事件以及类型注册到内核中并监听每个事件是否发生!
什么是IO多路复用?
首先我们需要了解的是文件事件处理器的组成(1.多个客户端连接 2.IO多路复用程序 3.文件事件分派器 4.事件处理器)
其中的流程如下图所示:
IO多路复用程序的原理:
a.IO多路复用程序的原理是基于操作系统提供的select、poll或epoll等系统调用函数。
b.当程序监听多个套接字时,它会向操作系统注册这些套接字,并让操作系统监视它们上面的读写事件。
b.当有任何一个套接字准备好了读写操作时,操作系统会通知程序,程序就可以开始进行读写操作
2.Redis为何不使用多线程?
原因如下:
1.单线程编程相对容易且更容易维护
2.多线程会产生死锁,线程上下文切换等一系列问题
3.Redis的性能瓶颈不在CPU,主要是在内存和网络
3.Redis在6.0之后为何又引入了多线程?
其主要目的是为了提高网络IO读写性能(Redis6.0 引⼊多线程主要是为了提⾼⽹络 IO 读写性能 多线程如何提高网络IO读写性能)
4.Redis给缓存数据设置过期的时间?Redis是如何判断数据过期的?过期的数据删除策略?
原因如下:
1.试想着如果对所有缓存数据都一直保存的话,那么内存分分钟爆炸,然后有些短信验证码我们设计的可能就只需要一分钟有效,就需要我们去设置过期时间
2.至于是如何判断数据过期的主要是通过 过期字典expires(可以看作hash表)来保存数据过期的时间 毫秒精度
3.常用的过期数据删除策略主要是惰性删除(只会在去除key的时候才对数据进行过期检查,缺点是可能会造成太多过期key没有被删除)与定期删除(每隔一段时间抽取一批key执行删除过期key的操作)
4.Redis 使用的是惰性过期机制,即不会在 key 过期时立即删除数据,而是等到下次访问这个 key 时再检查它是否过期,如果过期则删除。这种机制的优点是可以避免一些性能问题,如频繁地删除大量过期的键值对。
5.当一个 key 设置了过期时间后,Redis 就会将这个 key 的过期时间记录在一个名为 expire 的字典中,并将该字典保存在内存中。每当我们访问这个 key 时,Redis 都会先检查 expire 字典中是否存在该 key 的过期时间,如果存在且过期时间小于当前时间戳,则 Redis 会将该 key 标记为过期并返回空值或者删除该 key(具体取决于配置选项)。
6.另外,Redis 还提供了主动删除过期 key 的功能,该功能被称为定期删除。Redis 会以一定的频率扫描内存中的所有 key,查找已过期的 key 并删除。这个频率由配置选项决定。
Redis内存淘汰机制?(针对可能存在定期删除和惰性删除漏掉了很多过期 key 的情况)
Redis提供了6种数据淘汰策略:
1.从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
2.从已设置过期时间的数据集中挑选将要过期的数据淘汰
3.从已设置过期时间的数据集中任意选择数据淘汰
4.当内存不足以容纳新写入数据时,在键空间中,移除最少使用的key(这个是最常用)
5.从数据集中任意选择数据淘汰
6.禁止驱逐数据(sb行为)
7.从已设置过期时间的数据集中挑选最不经常使用的数据淘汰
8.当内存不⾜以容纳新写⼊数据时,在键空间中,移除最不经常使⽤的 key
Redis的持久化机制(Redis熄火后重启数据还能恢复)
1.RDB(快照)持久化
什么是快照?当使用RDB快照进行持久化时,Redis会在指定的时间间隔内将内存中的数据库状态保存到磁盘上,这个过程是通过将当前Redis数据库的状态生成一个压缩的二进制文件来完成
优点:
- RDB快照可以将Redis数据库在指定时间间隔内生成一个压缩的二进制文件,用于恢复数据,操作简单;
- RDB快照相对于AOF持久化,在写入大规模数据时占用内存较少,数据恢复速度也相对较快。
缺点:
- 由于RDB快照只保存某个时间点的数据库状态,如果Redis发生故障或意外关闭,最后一次快照之后的所有修改都会丢失;
- 如果应用程序需要频繁地修改数据库,建议不要使用RDB快照作为唯一的持久化方式,否则可能会导致数据丢失、不一致等问题;
- 在进行快照的时候,Redis会占用一些额外的CPU和IO资源,可能会影响应用程序的性能。
2.AOF(追加文件)持久化
什么是AOF?当使用AOF进行持久化时,Redis会将每一个写操作追加到一个只进行追加操作的日志文件中,以此来记录所有修改数据库状态的指令!
优点:
- AOF持久化可以记录每一个命令的执行过程,保证数据库状态的完整性,即使正在进行一些写操作,也不会造成数据丢失;
- AOF持久化支持多种同步策略,可以根据实际需要来选择合适的同步策略,以保护数据的安全性和一致性;
- 由于AOF持久化是追加操作,相对于RDB快照来说,数据恢复速度更快
缺点:
- AOF持久化需要进行频繁的写入操作,可能会影响到Redis本身的性能;
- AOF持久化在数据量较大时占用的磁盘空间也更大
![](https://i-blog.csdnimg.cn/blog_migrate/b3df85137e4886e849c7b81bc7cbf01d.png)
解决办法:
a.缓存无效key:如果缓存和数据库都查不到某个 key 的数据就写⼀个到 Redis 中去并设置过期时间(可能会导致缓存大量无效key)
b.布隆过滤器:利用布隆过滤器来判断给定的数据是否存在于海量数据当中,把所有可能存在的请求的值都存放在布隆过滤器中,当⽤户请求过来,先判断⽤户发来的请求的值是否存在于布隆过滤器中;
c.布隆过滤器的处理原理如下:
1.利用多个哈希函数将元素映射到一个位数组中,并将对应的位标记为1
2.当查询一个元素时,将该元素同样经过多次哈希函数映射到位数组中
3.并检查对应的位是否都为1,若有任何一个位标记为0,则说明该元素不在集合中。
2.双写模式:在写入数据库时,同时更新缓存。这种方法可以确保缓存和数据库的数据始终保持一致。
3.延迟双写模式:先更新数据库,再异步地更新缓存。这种方法可以减轻对数据库的负载,同时确保最终一致性
26.如何保证redis的热点数据不过期
设置合适的过期时间:对于那些经常被访问的热点数据,可以设置一个较长的过期时间,以确保它们不会过期。在设置过期时间时需要考虑到业务需求和硬件设备的性能,避免内存占用太高或者对系统性能造成不良影响。
使用 Redis 持久化功能:Redis 支持多种持久化方式,包括 RDB 和 AOF。在使用这些持久化方式时,可以将热点数据定期写入磁盘,以确保即使 Redis 服务崩溃或重启,这些数据也不会丢失。通过持久化功能,可以实现数据的可靠性和持久性,并降低数据丢失的风险。
除了以上两个方法,还可以结合 Redis 集群、主从复制等技术来实现热点数据的高可用性和可靠性。例如可以使用 Redis 集群将热点数据分布到多个节点上,以提高负载均衡和可用性;又或者可以使用 Redis 主从复制来实现热点数据的备份和读写分离,以提高系统的并发处理能力和稳定性。
40.redis主从复制、
1.Redis 主从复制是指在 Redis 集群中,主节点将自己的数据同步到从节点,从而实现数据备份和负载均衡的机制。
2.当主节点接收到一个写请求时,它会先将数据更新到自己的内存中,然后通过网络发送给从节点,并在本地记录下已发送的信息的偏移量。
3.从节点接收到数据后,会将其更新到自己的内存中,并在本地记录下自己已经接收到的信息的偏移量。
4.当主节点发生故障或者网络不稳定时,从节点可以使用本地记录的偏移量继续向其他从节点请求数据,从而避免数据丢失
41.redis原子性的实现机制(单线程 没反应过来)
Redis的原子性是通过单线程执行和事务机制来实现的,其主要步骤如下:
客户端发送MULTI命令表示开始一个新的事务,并将多个操作打包成一个队列。
Redis将这些操作暂存起来,并返回一个"QUEUED"响应。
客户端继续发送其他命令,Redis将这些命令放入队列中。
客户端发送EXEC命令,表示提交整个事务。
Redis依次执行队列中的所有命令,如果其中任何一个命令执行失败,则整个事务都会被回滚。
Redis将所有结果打包成一个数组,返回给客户端。
在事务过程中,客户端还可以使用WATCH命令监视一个或多个键,当这些键在事务执行期间被修改时,事务会被终止并返回一个错误响应。同时,还可以使用DISCARD命令取消一个事务。
62.redis怎么处理高并发,几种思路
Redis 作为一种内存数据库,对于高并发场景有着良好的支持和优化思路。下面介绍几种 Redis 处理高并发的常见思路:
消息队列:Redis 可以作为消息队列来处理高并发场景。通过将任务存储在 Redis 中,并使用多个消费者同时处理任务,可以提高系统的并发性能和处理能力。
分布式锁:Redis 的分布式锁机制可以用于保证数据的原子性和一致性。通过添加锁来限制只有一个客户端能够访问共享资源,避免并发操作带来的问题。
缓存:Redis 的缓存机制可以用于加速读取操作,减少对后端数据库的访问。通过将热点数据存储在 Redis 中,可以大幅降低数据库压力,提高系统性能。
集群:Redis 支持集群模式,通过横向扩展节点数量,可以提高系统的负载能力和可用性。同时也需要注意集群中的数据同步与节点故障的处理等问题。
63.redis实现原理
Redis 是一种高性能的开源内存数据库,采用键值存储方式,支持多种数据类型和复杂的数据结构。下面是 Redis 的实现原理:
内存数据库:Redis 将所有数据都存储在内存中,因此具有极快的读写速度。同时,为了避免内存溢出等问题,Redis 也提供了持久化机制,将数据定期写入磁盘。
单线程模型:Redis 使用单线程模型来处理客户端请求,通过使用非阻塞 I/O、事件驱动等技术,从而能够提高系统并发性能和响应速度。
客户端/服务器模型:Redis 采用客户端/服务器模型,可以同时服务多个客户端,并通过网络协议(例如 TCP/IP)进行通信。
多种数据类型:Redis 支持多种数据类型,包括字符串(String)、哈希表(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。每种数据类型都有特定的操作命令,例如 GET、SET、HGETALL、LPUSH、SADD 和 ZRANGE 等。
操作原子性:Redis 中的大部分操作都是原子性的,意味着在执行这些操作时,要么全部成功完成,要么全部失败回滚。这样可以保证数据的一致性和可靠性。
高可用性:Redis 提供了多种高可用性方案,包括主从复制、哨兵和集群等。通过这些机制,可以提高系统的可用性和容错性
66.redis有一个key有过期时间,这时候一直有客户端的命令去set这个key,会有什么问题?
过期时间无效:如果客户端一直更新这个 key 的值,那么过期时间就会失效,从而导致这个 key 永不过期。
性能损耗:每次客户端更新这个 key 的值,都会导致 Redis 执行一次 SET 命令并将值写入内存。如果客户端频繁更新这个 key 的值,就会导致 Redis 内存频繁写入和回收操作,降低系统的性能表现。
内存泄漏:如果客户端更新这个 key 的值的速度远大于过期时间,那么 Redis 内存中可能会存在大量已经过期但是未被删除的 key,从而导致内存泄漏。这种情况下,需要使用 Redis 的内存淘汰策略或者手动清除过期的 key,以避免内存溢出等问题
79.流量削峰怎么做?
流量削峰是一个常见的系统性能优化技术,目的是尽可能地避免系统因为突发的高并发流量而崩溃。具体做法包括以下几个方面:
缓存:使用缓存可以减轻对数据库或其他后端服务的流量压力。可以将热点数据放置在 Redis 等缓存中,降低对数据库的访问频率。
队列:通过消息队列来实现流量削峰,把请求持久化到消息队列中,再按照一定的规则进行消费。这样可以将短时间内的流量进行平滑处理,避免瞬间的高并发导致系统宕机。
限流:限流可以控制系统的最大并发数,防止超出系统承载能力。可以采用令牌桶、漏桶等算法对请求进行限流。
异步处理:将一些处理量较大的业务异步化处理,例如图片上传、邮件发送等操作。这样可以将大量的计算和 I/O 操作移至异步线程中,释放主线程的资源。
分层架构:对于高并发的系统,可以采用分层架构以及微服务架构,将任务分配到不同的节点上,实现负载均衡
67.百万QPS登录怎么解决?
高性能硬件设备:首先需要使用高性能的硬件设备,例如高速网络接口卡、高速磁盘等,以满足海量请求的处理需求。
负载均衡:为了分摊并发请求的压力,可以采用负载均衡技术将传入的请求分散到多台服务器上进行处理。常见的负载均衡算法有轮询、随机、最少连接数等。
分布式缓存:使用分布式缓存技术(例如 Redis、Memcached 等)来缓存用户登录状态信息,减少数据库访问次数,提高系统响应速度和并发处理能力。
集群化部署:将系统部署在多台服务器上组成集群,实现分布式处理,提高系统的可用性和扩展性。需要注意避免数据不一致等问题。
异步处理:使用异步处理技术(例如消息队列、线程池等)来异步处理登录请求,降低系统的响应延迟和资源消耗,并提高系统的稳定性和抗压能力。
优化 SQL 查询:尽量避免复杂的 SQL 查询操作和大量的数据库读写操作,可以通过索引优化、分库分表等技术来提高数据库查询效率和吞吐量。
限流控制:在系统出现瞬时高并发请求时,需要采用限流措施(例如令牌桶、漏桶算法)来控制请求的并发数,保证系统不会因为请求过多导致崩溃或者响应变慢