当前位置: 首页 > news >正文

Redis 详解

简介

Redis 的全称是 Remote Dictionary Server,它是一个基于内存的 NoSQL(非关系型)数据库,数据以 键值对 存储,支持各种复杂的数据结构

为什么会出现 Redis?

Redis 的出现是为了弥补传统数据库在高性能要求下的不足传统的关系型数据库在读写速度、并发处理和扩展性上有时不能满足某些高并发场景的需求。尤其是在互联网应用中,对于海量数据的处理、低延迟和高吞吐量的要求越来越高,Redis 提供了一种高效且灵活的解决方案

Redis的作用

大量在以下方面使用:
缓存系统: Redis 经常被用作缓存数据库,减轻传统关系型数据库的压力,提升访问速度。例如,在 Web 应用中,Redis 可以缓存数据库查询结果,当用户请求相同的数据时,可以直接从 Redis 获取,而不需要每次都访问数据库。这样可以大幅提高响应速度和降低数据库负载

高性能的数据存储: Redis 是一个内存数据库,它将数据存储在内存中,因而读取和写入速度非常快。它也支持持久化功能,可以定期将数据存储到硬盘上,避免丢失数据。

消息队列Redis 支持发布/订阅模式以及基于列表的数据结构,可以用作消息队列系统处理高并发的消息传递。例如,生产者将消息写入 Redis 队列,消费者从队列中获取消息进行处理,支持高效的异步任务处理。

分布式锁: Redis 提供了分布式锁的实现,可以解决多个进程或服务对同一资源的并发控制问题确保在分布式环境下只有一个线程能够执行特定的操作

实时分析和计数: Redis 可以处理实时的数据分析和计数,比如网站访问量统计、实时数据处理等。它的高性能使得它能够在大规模、高并发的环境下工作。

Redis的特点:

高性能:Redis 是内存存储,数据操作速度极快,读写性能远高于传统的磁盘数据库。
持久化:虽然 Redis 是内存数据库,但它提供了数据持久化的机制,可以将内存中的数据异步地保存到硬盘,防止数据丢失。
丰富的数据类型:Redis 支持多种复杂的数据结构,如字符串、哈希、列表、集合、排序集合等。
原子操作:支持原子操作,可以通过管道(Pipelining)方式批量执行多个命令。
发布/订阅模式:支持消息队列模式,可以实现不同服务之间的异步通信。
高可用与分布式:通过 Redis 的主从复制、哨兵模式以及集群模式,可以实现高可用性和水平扩展

Redis的常用数据类型:

常用类型有String,list,hash,set,zset
高级类型Bitmap(位图)、HyperLogLog、Geospatial(地理位置)、Streams(流)

String(字符串):

最简单的类型,一个字符串最多可以是 512MB。

使用场景
缓存:比如缓存用户的会话信息、网页、API 响应等。
计数器:通过 INCR 或 DECR 命令可以很方便地实现简单的计数器(例如访问量、点赞数等)。
限流:通过字符串类型和 INCR 命令,可以实现请求次数的计数,用于实现 API 的限流。

List(列表):

按插入顺序存储多个字符串。

使用场景:
消息队列:利用 Redis 列表,可以实现一个高效的消息队列。比如生产者将消息推送到列表的一端,消费者从另一端弹出并处理消息。
任务调度:可以将待处理的任务以列表形式存储,消费者通过从队列中弹出任务来进行处理。

Set(集合):

存储不重复的字符串元素。

使用场景
去重:适用于需要去重的场景,比如存储用户的浏览记录或点赞信息。
标签或兴趣管理:比如管理用户兴趣标签,用户可以关注不同的兴趣,而集合确保每个兴趣标签只会出现一次。
推荐系统:通过集合的交集、并集等操作,可以实现推荐系统的功能,例如找出共同兴趣的用户。

Sorted Set(有序集合):

和 Set 类似,但每个元素都有一个分数,可以根据分数对元素进行排序。

使用场景
排行榜:例如网站的用户积分排行榜,玩家的游戏得分排行榜,Redis 会自动根据分数排序并提供快速查询。
实时推荐:根据用户活跃度、评分等进行动态排序,并实时更新推荐结果。
限时优惠:可以存储和查询具有过期时间的优惠活动信息,例如商场的打折商品列表。

Hash(哈希):

存储键值对的集合,适合存储对象。

使用场景:
用户信息存储:可以存储一个用户的各种属性(例如用户的姓名、年龄、邮箱等)。每个属性对应哈希中的一个字段。
配置项:存储一些系统的配置信息,便于快速读取和修改。

持久化

redis是数据存储在内存中,那么如果服务器重启之后或者redis崩溃之后数据不就丢失了吗
所以redis为了防止这种情况支持多种持久化方式,以便在服务器重启后仍然能够恢复数据。Redis 主要有两种持久化方式:**RDB(快照持久化)**和 AOF(追加文件持久化)。这两种持久化方式可以单独使用,也可以结合使用。

RDB(快照持久化)

RDB 是 Redis 的默认持久化方式,它通过在指定时间点生成数据库的快照来实现持久化。快照是一个包含所有 Redis 数据的二进制文件,通常是 .rdb 文件

工作原理:
Redis 会根据配置定期执行“生成快照”的操作,将当前内存中的数据保存到硬盘上的 RDB 文件中。

默认情况下,可以配置触发快照的条件,如某个时间内有多少次写操作,或者某段时间内数据是否发生了变化等。
RDB 文件存储的是 Redis 的完整数据快照,而不是增量更新。

优点:
快照生成过程相对较快
数据文件较小,适合用于数据恢复。
不会影响 Redis 的读写操作,因为生成快照时 Redis 会通过 **fork(多进程)**创建子进程。

缺点
如果 Redis 在生成快照期间崩溃可能会丢失未写入磁盘的数据。
恢复速度可能较慢,特别是在数据量很大的时候

配置:在 redis.conf 配置文件中,常见的 RDB 配置项如下:

save 900 1      # 900秒内有1次写操作时生成快照
save 300 10     # 300秒内有10次写操作时生成快照
save 60 10000   # 60秒内有10000次写操作时生成快照
RDB 快照的生成和覆盖过程

假设你设置 Redis 每 1 分钟生成一个 RDB 快照:

第一分钟:假设数据库有 3 条记录,RDB 会生成包含这 3 条记录的快照文件。此时,dump.rdb 文件中包含了这 3 条记录。

第一到第二分钟之间新增了 5 条记录:在第二分钟到来时,Redis 会根据配置的策略生成新的 RDB 快照。新的快照会覆盖掉上一个快照,并且这次的快照会包含所有的记录,包括之前的 3 条和新增的 5 条记录。所以此时,新的 RDB 文件会包含 8 条记录。

第二到第三分钟之间新增了 7 条记录:如果 Redis 在此时崩溃或重启,RDB 文件会保留最后一次成功生成的快照,也就是第二分钟时的 8 条记录,而不会包含第三分钟内新增的 7 条记录。

总结:RDB 文件确实是每次生成快照时覆盖之前的文件。即使 Redis 崩溃后重启,它也只会恢复到最后一次成功保存的快照,这可能导致部分数据丢失,尤其是在上次快照之后发生的修改数据,这就是为什么RDB效率高,但是不安全

AOF(追加文件持久化)

AOF 通过记录所有的写操作(每次修改数据的命令)到一个日志文件中来实现数据持久化。这个文件通常是 appendonly.aof

工作原理:
Redis 会将每个写操作(如 SET、HSET 等)追加到 AOF 文件中,这些操作在 Redis 重启后会重新执行以恢复数据。

AOF 文件会包含所有的写操作,Redis 会按照命令顺序依次执行,从而恢复出原来的数据。

AOF 提供了三种不同的同步策略
always每次操作后都将命令写入 AOF 文件,性能最差,但数据安全性最好。
everysec每秒钟将 AOF 文件写入一次,是默认选项,兼顾性能和数据安全。
no完全不进行同步,性能最好,但可能丢失所有未同步的数据。

优点
提供更高的数据安全性,AOF 可以保证数据尽可能不丢失
可以配置同步策略,灵活调整性能和持久化的安全性。

缺点:
AOF 文件会随着写操作的增多而变得较大
由于每次写操作都需要记录到文件中,AOF 会对性能产生一定的影响。
Redis 重启时,恢复过程可能比 RDB 更慢,尤其是在写操作很多的情况下。

配置:在 redis.conf 配置文件中,常见的 AOF 配置项如下:

appendonly yes           # 启用 AOF 持久化
appendfsync everysec     # 每秒同步一次 AOF 文件
no-appendfsync-on-rewrite yes # 重写期间不进行同步

RDB + AOF 混合持久化

Redis 允许同时开启 RDB 和 AOF 持久化,这样可以利用两者的优点,避免单独使用时的缺点。

自redis4之后对更改了RDB + AOF 混合持久化的流程

混合持久化的基本流程
  1. 判断是否开启 AOF 持久化:如果 Redis 配置中开启了 AOF 持久化,Redis 会继续执行混合持久化的后续流程;如果未开启 AOF,Redis 会直接加载 RDB 文件进行恢复。
  2. 检查 appendonly.aof 文件是否存在
    如果 AOF 文件存在,Redis 会继续执行混合持久化恢复流程。
    如果 AOF 文件不存在,Redis 会直接加载 RDB 文件进行恢复。
  3. 判断 AOF 文件是否包含 RDB 格式数据
    Redis 会检查 AOF 文件的开头是否是 RDB 格式的数据头。这个特性是混合持久化的关键。
    如果 AOF 文件的开头包含 RDB 格式的数据,Redis 会首先加载这些 RDB 数据,然后继续加载 AOF 文件中剩余的操作日志。
    如果 AOF 文件的开头没有 RDB 格式数据,Redis 会直接加载整个 AOF 文件。
混合持久化的文件结构

在 Redis 4.0 之后,混合持久化将 RDB 数据和 AOF 日志存放在同一个文件中。这意味着 Redis 在生成持久化文件时,会先生成一个 RDB 快照(通常是某个时间点的全量快照),然后将自上次持久化以来的增量写操作(AOF)追加到这个文件中。这个文件是一个混合文件,它包含了两部分内容:

RDB 格式数据:在混合持久化文件的开头部分,包含了当前数据库的 RDB 快照内容。这个部分的数据格式与普通的 RDB 文件相同。

AOF 格式的增量操作:在 RDB 数据之后,紧跟着是自上次 RDB 持久化之后发生的增量操作,这部分是 AOF 格式的,记录了每个写操作(如 SET、DEL 等)。

具体的存储方式

假设你设置了每 1 分钟生成一个 RDB 快照,而每分钟新增 5 条数据。混合持久化在生成文件时的存储内容大致如下:

假设场景:
每 1 分钟生成一个 RDB 快照。
每分钟新增 5 条数据,假设这些数据的操作是 SET key:value(这里以 5 条为例)。
混合持久化文件的结构:
第 1 分钟的 RDB 快照:在文件的开头会有一个完整的 RDB 格式的快照,包含你数据库的所有数据(比如 10 条记录)。

这部分数据是全量快照,比如:

RDB header
数据条目 1 (key1: value1)
数据条目 2 (key2: value2)
...
数据条目 N (keyN: valueN)

自上次 RDB 快照之后的增量 AOF 操作:在 RDB 快照之后,会有一段 AOF 格式的增量操作,这部分操作会记录每一个写操作。

假设在第 1 分钟到第 2 分钟之间新增了 5 条数据(SET key1 value1, SET key2 value2, …),那么在混合持久化文件中会紧跟 RDB 数据之后记录这些操作:

AOF操作 1 (SET key1 value1)
AOF操作 2 (SET key2 value2)
AOF操作 3 (SET key3 value3)
AOF操作 4 (SET key4 value4)
AOF操作 5 (SET key5 value5)

然后里面的格式大致如下

RDB快照:
key1: "value1"
key2: "value2"
key3: "value3"AOF增量操作:
SET key4 "value4"
SET key5 "value5"
SET key6 "value6"
SET key7 "value7"
SET key8 "value8"

下一个 RDB 快照:在第 2 分钟时,Redis 会生成一个新的 RDB 快照,这时会记录整个数据库的当前状态(例如,除了第 1 分钟的 10 条记录外,再新增了 5 条)。这个快照会覆盖前一个 RDB 快照。

自第 2 分钟以来的增量 AOF 操作:在第 2 分钟到第 3 分钟之间新增的 5 条数据,也会记录在增量 AOF 部分。

总结

混合持久化将 RDB 快照 和 增量 AOF 操作 存放在同一个文件中。
RDB 文件存储的是一个完整的数据库快照,而AOF 文件存储的是自上次 RDB 快照后的增量操作(如每个 SET、DEL 等命令)。
在 Redis 重启时,Redis 会先加载 RDB 快照文件,恢复大部分数据,然后根据增量 AOF 操作补充那些在 RDB 快照之后的修改操作,从而恢复到最后的数据库状态。

问题

为什么 RDB 生成效率更快?

RDB 是通过生成一个数据库的“快照”来实现数据持久化的。具体来说,Redis 会将当前内存中的数据存储到一个二进制的 .rdb 文件中。这个过程是由 Redis 的子进程(通过 fork 创建)来执行的主进程继续处理客户端的请求。快照生成时,子进程会复制当前的内存数据并保存到磁盘。

RDB 更高效的原因

RDB 是通过一次性保存所有数据的快照来实现持久化的,整个过程是比较简单且高效的,尤其是在数据量比较小或保存间隔较长时。
生成快照的过程不会影响 Redis 主进程的性能,因为它是通过 fork 创建子进程的,主进程不需要等待子进程的写入操作,从而可以继续响应客户端请求。
但是,需要注意的是,RDB 生成快照的过程在数据量比较大的时候可能会变得较慢,因为它需要将所有数据(无论是大还是小)都写入硬盘。

AOF 为什么更安全?

AOF 是通过将每个写操作(如 SET、HSET 等)追加到日志文件中来记录数据。每次写操作发生时,Redis 会将相应的命令记录到 AOF 文件中,从而确保可以在 Redis 重启时通过重新执行这些命令恢复数据。

AOF 更安全的原因:

AOF 提供了三种不同的同步策略,可以精确控制数据持久化的安全性。特别是 appendfsync always(每次写操作都同步到磁盘)能够最大程度地保证数据不会丢失。
即便 Redis 崩溃,AOF 文件也能记录所有的写操作,因此通过重放 AOF 文件中的命令可以恢复所有的操作。
AOF 的安全性来源于它记录了每一个写操作,在 Redis 重启时,只需要按顺序执行这些操作,就可以精确地恢复数据。

重写AOF
为什么要重写AOF

首先,AOF 文件记录了所有的写操作,包括 SET、HSET、DEL 等命令。这意味着每个写操作(无论是插入、修改还是删除)都会被记录下来。而因为 Redis 是一个高性能的内存数据库,通常对数据进行频繁的修改,比如 SET 命令可能会多次修改相同的键值

这样,随着时间的推移,AOF 文件会记录下大量的“修改操作”,这些操作的执行结果有可能是“覆盖之前的数据”,但是它并不意味着那些修改操作本身是必要的。实际上,我们可以通过重写 AOF 文件来去掉这些不必要的操作,保留最新的数据状态

因此为什么需要 AOF 重写?
AOF 重写的目的是: 缩小文件的大小,同时去除不必要的历史修改操作(例如,某个键的多个 SET 操作),确保 AOF 文件只记录当前数据的最终状态,而不需要记录每一步修改。通过这种方式,AOF 文件的大小可以被有效控制。

举个例子:
假设有以下操作序列:

SET key “hello”
SET key “world”
DEL key
假设你的 key 原始值是 “hello”,然后它被 SET 改为 “world”,最后被删除。如果不进行重写,AOF 文件会记录三条命令:

SET key "hello"
SET key "world"
DEL key

但是在 Redis 重新启动时,这三条命令会依次执行,导致 “world” 变成了 nil(因为最后是删除操作)。实际上,你只需要在 AOF 文件中保留一个DEL key 操作,而不需要再保留之前的 SET 操作。

AOF 重写过程:
重写过程中,Redis 会重新扫描当前的数据库状态,并生成一个新的 AOF 文件,其中仅记录恢复当前数据所必需的最少命令。
比如,AOF 重写后,新的文件可能只包含 DEL key,因为这是恢复当前状态的唯一必要命令。
通过 AOF 重写,Redis 会减少不必要的历史修改操作,从而减少文件大小。

缓存问题

咱们使用redis的时候经常作为缓存,因为是内存数据库具有高性能,但是作为缓存会有以下问题,所以设计的时候需要考虑到以下场景的情况

缓存穿透、缓存击穿、缓存雪崩

缓存穿透

定义:
缓存穿透是指请求的数据在缓存中没有命中,并且请求的数据在数据库中也不存在。也就是说,缓存没有这个数据,数据库查询也没有这个数据。由于没有缓存,可以直接访问数据库,导致大量无效请求打到数据库,造成数据库压力,无法利用缓存的优势。

为什么会有缓存穿透:
不存在的数据:有些请求可能查询的是根本不存在的数据(例如恶意请求、非法请求等)。
缓存未命中:缓存中的数据不存在或已过期,因此会查询数据库。

解决方案:

缓存空数据:

对于查询结果为空的数据(即数据库没有这个数据),可以在缓存中也存一个空值,设置一个较短的过期时间。这样,下次如果再有相同的请求,就能从缓存中直接返回空值,避免再次访问数据库。

前端防护:

通过接口层或前端校验来过滤非法请求,确保不向缓存或数据库发送无效请求。

缓存击穿(Cache Breakdown)

定义:
缓存击穿是指某一时刻,大量请求访问一个过期的缓存数据,也叫热点数据,而缓存数据已经过期或失效。此时,所有的请求都会直接访问数据库,导致数据库瞬间压力增大,性能下降

解决方案:

互斥锁机制:

在缓存过期时,只允许一个请求去查询数据库并更新缓存,其它请求需要等待。

代码

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class CacheBreakdownSolution {private RedisClient redisClient;private DatabaseClient databaseClient;private Lock lock = new ReentrantLock();public String getData(String key) {// 先尝试从缓存中获取数据String cacheValue = redisClient.get(key);if (cacheValue == null) {  // 如果缓存中没有数据lock.lock();  // 获取锁,防止多个线程同时查询数据库try {// 再次检查缓存是否已经被其他线程填充cacheValue = redisClient.get(key);if (cacheValue == null) {// 查询数据库String dbValue = databaseClient.query(key);if (dbValue == null) {redisClient.set(key, "empty", 60);  // 缓存空数据return null;}redisClient.set(key, dbValue, 3600);  // 缓存数据return dbValue;}} finally {lock.unlock();  // 释放锁}}return cacheValue;  // 如果缓存中有数据,直接返回}
}
延长过期时间

通过延长热点数据过期时间,减少发生的概率

缓存雪崩

定义
缓存雪崩是指在同一时刻,大量缓存数据集中失效(比如缓存批量过期),这时大量请求直接访问数据库,导致数据库承受巨大压力,甚至崩溃。
可能情况:
缓存同时过期:如果大量缓存设置了相同的过期时间,缓存一旦失效,就会在同一时刻大量过期,从而导致大量请求直接访问数据库。

解决方案

设置不同的过期时间:

避免所有缓存设置相同的过期时间,可以给不同的数据设置不同的过期时间,降低缓存同时过期的概率。

使用永不过期的缓存:

对于某些数据,可以通过将缓存设置为永不过期,避免频繁失效,但需要定期通过后台线程或任务来清理过期的数据。

预热缓存
降级机制:

当缓存失效并且访问量较大时,可以设计降级机制,对于一些不重要的数据返回默认值或者静态页面,减少数据库的负载。

部署模式

常见的部署模式包括 单机模式、主从模式、哨兵模式 和 集群模式。每种模式适用于不同的场景

单机模式

特点:单机模式是 Redis 最简单的部署方式,所有数据都存储在一个 Redis 实例中,只有一个 Redis 进程在运行。
用途:适用于数据量较小,或者对高可用性和扩展性要求不高的场景。通常用于开发和测试环境,或者一些简单的小型应用。

主从复制

特点:主从模式下,存在一个主节点(Master)和多个从节点(Slave)。主节点负责写操作和数据更新,而从节点负责读取数据,且从节点会从主节点同步数据。主从模式提高了读取性能,但主节点的故障会导致整个系统不可用。
用途:适用于读取压力较大的场景,通过从节点分担读取压力,提高读取性能。数据的高可用性较低,因为如果主节点宕机,从节点只能继续提供读服务,无法进行写操作。
使用场景:适用于读多写少的应用场景,例如缓存、日志存储、排行榜等。

配置方法:从节点通过 slaveof 指令指定主节点。 在从节点的 redis.conf 配置文件中,加入以下配置:

slaveof <master-ip> <master-port>

也可以运行直接使用命令

redis-server --slaveof <master-ip> <master-port>

哨兵模式

特点:哨兵模式是 Redis 为了实现高可用性而提供的解决方案。哨兵(Sentinel)是一个独立的进程,它监控 Redis 实例的状态。如果主节点宕机,哨兵会自动选举一个从节点提升为主节点,并通知客户端新的主节点地址。哨兵还可以提供自动故障转移和配置更新。
用途:适用于要求高可用性的场景,通过自动故障转移来保证系统的稳定性。在主节点发生故障时,不会影响系统的正常运行。
使用场景:适用于生产环境中需要高可用的应用,尤其是对数据写入要求较高的场景,如分布式系统、实时数据处理等。

配置方法:每个哨兵需要独立的配置文件。配置文件名通常为 sentinel.conf,并在文件中指定监控的主节点。

创建一个哨兵配置文件 sentinel.conf,并在文件中配置要监控的主节点信息:

sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

解释:
mymaster 是要监控的主节点名称。
127.0.0.1 和 6379 是主节点的 IP 地址和端口。
2 是最少的哨兵数(需要多少个哨兵同意才能执行故障转移)。
down-after-milliseconds 是判定主节点宕机的时间。
failover-timeout 和 parallel-syncs 分别设置故障转移的超时和同步数量。

其中为什么不配置从节点,因为哨兵模式是基于主从模式的,我们知道主节点之后就知道从节点了

启动多个哨兵来提供冗余和容错能力:

redis-server /path/to/sentinel1.conf --sentinel
redis-server /path/to/sentinel2.conf --sentinel

集群模式(Cluster)

**主从和哨兵都没有解决一个问题:单个节点的存储能力和访问能力是有限的。**集群模式把数据进行分片存储。集群的键空间被分割成16384个slots(即hash卡槽),通过hash的方式将数据分到不同的分片上。某个主节点宕机,那这个主节点下的从节点会通过选举产生一个主节点,替换原来的故障节点

特点:集群模式是 Redis 为了解决水平扩展(sharding)问题而设计的。它将数据分布到多个 Redis 节点上,通过哈希槽(Hash Slot)将数据分散到不同的节点。集群模式支持自动分片、自动故障转移等特性,支持多个主节点和从节点,具有较高的扩展性和可用性。
用途:适用于数据量大、需要水平扩展的场景,能够提供更高的性能和可用性。集群模式通过分片来提高存储容量和处理能力。
使用场景:适用于需要大规模数据存储、高并发访问的应用,如社交网络、大数据分析、推荐系统等。

为什么Redis处理速度快

主要是Redis有一些4个特征

  1. 内存存储
  2. 单线程
  3. 多路i/o复用
  4. 数据结构

内存存储:

内存访问速度:内存是计算机中 最快的存储介质,其读取速度和写入速度非常高,通常在纳秒级别(ns)。内存是直接由 CPU 控制的,数据可以直接被读取到 CPU 中进行处理,不需要额外的操作。
磁盘访问速度:与内存相比,传统的硬盘(特别是机械硬盘)访问速度慢得多。机械硬盘的读写速度通常在毫秒级(ms)或微秒级(µs),远远慢于内存。即使是 固态硬盘(SSD),它的访问速度也只能达到内存的一个较低级别,大约是纳秒级的数千倍到万倍,虽然 SSD 要比传统硬盘快,但还是不及内存。

单线程

Redis在设计过程中使用的是单线程,为什么不使用多线程?
首先,Redis 使用的是 单线程模型。所有的客户端请求都通过一个线程进行处理,看似这是一个限制,但实际上,这反而是 Redis 性能高的关键之一。

没有严重的上下文切换锁的性能开销,以及实现的复杂度,Redis单线程已经够用

i/o多路复用

这里虽然Redis是单线程,但是使用i/o多路复用,以及利用事件驱动

事件驱动:Redis 使用事件循环的方式处理请求,所有的请求(无论是读还是写操作)都通过一个事件循环队列进行排队,Redis 会按照事件的顺序依次处理请求。这个事件循环是非阻塞的,意味着当 Redis 正在处理某个请求时,它不会因等待某个 I/O 操作(如网络读取或磁盘操作)而阻塞其他操作。

通过这种方式,Redis 不会在处理请求的过程中空闲等待,而是会一直保持高效地执行其他任务

I/O 多路复用:I/O 多路复用技术(如 epoll,select等)允许 Redis 在同一线程中同时监听多个网络连接的状态。Redis 可以在一个线程中同时处理多个客户端的请求,而不是每次都为每个客户端请求创建一个新的线程。这是通过 I/O 多路复用机制来完成的。

具体来说,Redis 通过 I/O 多路复用机制,能够在网络层同时 监听多个客户端的连接,并且在数据准备好时,迅速响应。这与传统的阻塞 I/O 有本质的不同。传统的阻塞 I/O 会让线程阻塞在等待数据准备的状态,直到数据准备好才能继续执行,而 Redis 通过 I/O 多路复用,能够在同一线程中 高效地轮询多个客户端的连接,确保在等待数据的过程中不浪费任何 CPU 时间。

相关文章:

Redis 详解

简介 Redis 的全称是 Remote Dictionary Server&#xff0c;它是一个基于内存的 NoSQL&#xff08;非关系型&#xff09;数据库&#xff0c;数据以 键值对 存储&#xff0c;支持各种复杂的数据结构 为什么会出现 Redis&#xff1f; Redis 的出现是为了弥补传统数据库在高性能…...

亲测有效!解决PyCharm下PyEMD安装报错 ModuleNotFoundError: No module named ‘PyEMD‘

解决PyCharm下PyEMD安装报错 PyEMD安装报错解决方案 PyEMD安装报错 PyCharm下通过右键自动安装PyEMD后运行报错ModuleNotFoundError: No module named ‘PyEMD’ 解决方案 通过PyCharm IDE python package搜索EMD-signal&#xff0c;选择版本后点击“install”执行安装...

Java 设计模式 二 单例模式 (Singleton Pattern)

单例模式 (Singleton Pattern) 是一种常见的设计模式&#xff0c;属于创建型模式。它的核心思想是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。通常用于那些需要全局控制的场景&#xff0c;比如配置管理、日志系统、数据库连接池等。 1. 单例模式的…...

golang网络编程

socket编程 socket图解 Socket是BSD UNIX的进程通信机制&#xff0c;通常也称作”套接字”&#xff0c;用于描述IP地址和端口&#xff0c;是一个通信链的句柄。Socket可以理解为TCP/IP网络的API&#xff0c;它定义了许多函数或例程&#xff0c;程序员可以用它们来开发TCP/IP网…...

kotlin内联函数——takeIf和takeUnless

1.takeIf 当对一个对象调用takeIf时&#xff0c;如果对象满足给定的判断条件&#xff0c;则返回该对象&#xff1b;否则&#xff0c;返回null。因此&#xff0c;takeIf是对单个对象进行过滤的函数。例如&#xff0c; class User {var name: String? nullvar age 99fun set…...

计算机网络 (54)系统安全:防火墙与入侵检测

前言 计算机网络系统安全是确保网络通信和数据不受未经授权访问、泄露、破坏或篡改的关键。防火墙和入侵检测系统&#xff08;IDS&#xff09;是维护网络系统安全的两大核心组件。 一、防火墙 定义与功能 防火墙是一种用来加强网络之间访问控制的特殊网络互联设备&#xff0c;它…...

第38周:猫狗识别 (Tensorflow实战第八周)

目录 前言 一、前期工作 1.1 设置GPU 1.2 导入数据 输出 二、数据预处理 2.1 加载数据 2.2 再次检查数据 2.3 配置数据集 2.4 可视化数据 三、构建VGG-16网络 3.1 VGG-16网络介绍 3.2 搭建VGG-16模型 四、编译 五、训练模型 六、模型评估 七、预测 总结 前言…...

【力扣Hot 100】矩阵1

矩阵置零&#xff1a;1. 开两个数组判断该行/该列是否有0&#xff1b;2. 用第0行/第0列分别判断该列/该行是否有0 螺旋矩阵&#xff1a;记录方向&#xff0c;一直按某方向前进&#xff0c;遇到障碍方向就变一下 1. 矩阵置零 给定一个 *m* x *n* 的矩阵&#xff0c;如果一个元…...

量子编程语言:Qiskit 与 Cirq

在量子计算的领域&#xff0c;开发者已经可以使用一些专门为量子计算设计的编程语言和框架。其中&#xff0c;Qiskit 和 Cirq 是两个非常流行的选择&#xff0c;它们为不同的量子计算机提供编程接口&#xff0c;帮助开发者理解量子电路的设计和执行。 1. Qiskit Qiskit 是 IBM…...

leetcode 124. 二叉树中的最大路径和

题目&#xff1a;124. 二叉树中的最大路径和 - 力扣&#xff08;LeetCode&#xff09; 定义一个节点的“最大单向路径和”是single&#xff0c;single有以下几种情况&#xff1a; 只有该节点该节点左儿子的single该节点右儿子的single 设答案是节点 node 为根节点&#xff0…...

程序员转型测试:解锁漏洞挖掘新旅程

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 程序…...

基于Springboot用axiospost请求接收字符串参数为null的解决方案

问题 ​ 今天在用前端 post 请求后端时发现&#xff0c;由于是以 Json对象的形式传输的&#xff0c;后端用两个字符串形参无法获取到对应的参数值 前端代码如下&#xff1a; axios.post(http://localhost:8083/test/postParams,{a: 1, b:2} ,{Content-Type: application/jso…...

# AI绘图中的Embedding、CLIP、Flux中的Clip与LCM SDXL加速生成解析

AI绘图中的Embedding、CLIP、Flux中的Clip与LCM SDXL加速生成解析 在现代AI绘图和深度学习中&#xff0c;涉及了多个复杂的概念和技术&#xff0c;这些技术在图像生成、训练加速以及多模态学习等方面起着至关重要的作用。在这篇博客中&#xff0c;我们将讨论几个关键概念&…...

警企联动齐发力、共筑反诈“防护墙”

2025年1月10日是第五个中国人民警察节,南通移动联合南通公安反诈中心,深入社区商圈,开展防范电信网络诈骗宣传活动,进一步增强广大人民群众的反诈意识和能力,全力守护好群众的“钱袋子”。 当日,活动现场一大早就呈现出一片忙碌景象,工作人员支起摊位,将各类精心制作的反诈宣传…...

Node.js HTTP模块详解:创建服务器、响应请求与客户端请求

Node.js HTTP模块详解&#xff1a;创建服务器、响应请求与客户端请求 Node.js 的 http 模块是 Node.js 核心模块之一&#xff0c;它允许你创建 HTTP 服务器和客户端。以下是一些关键知识点和代码示例&#xff1a; 1. 创建 HTTP 服务器 使用 http.createServer() 方法可以创建…...

Alibaba Spring Cloud 十七 Sentinel熔断降级

概述 在微服务架构中&#xff0c;熔断与降级是保证系统稳定性的重要机制&#xff0c;能有效防止故障蔓延或雪崩效应。当某个服务出现异常、延迟过高或错误率过高时&#xff0c;触发熔断保护&#xff0c;将该服务“隔离”一段时间&#xff0c;避免影响整体系统的吞吐和可用性。 …...

linux——网络基础

文章目录 目录 文章目录 踏入网络世界&#xff1a;探索 Linux 网络的无垠天地 一、网络发展 早期单机处理模式 网络发展的需求催生 网络发展后的优势对比 二、局域网or广域网 典型局域网架构 广域网连接多个局域网 二者关系 三、协议 语言层与汉语协议 通信设备层与电话机协议 …...

Spring Boot 集成 WebClient 实战教程 实现同步、异步请求处理以及响应式编程、响应式流、响应式Mono

该项目介绍springboot集成WebClient 实现服务的请求操作 示例中演示了,如何配置WebClient的请求头,请求参数等相关参数,实现同步、异步请求处理以及响应式编程、响应式流、响应式Mono。 为什么使用WebClient 不用RestTemplate 在 Spring Framework 5.0 及更高版本中,Res…...

健身房项目 Uniapp+若依Vue3版搭建!!

本次系统实现主要负责前端前端功能的实现。其中系统前端主要分为三大部分&#xff0c;首页&#xff0c;教练列表页&#xff0c;我的页面。 首页 首页的实现效果如图 1.会员卡组件 首页的Vip会员卡部分&#xff0c;团课活动的DataPicker&#xff0c;团课选择都采用了组件化封…...

(2)STM32 USB设备开发-USB虚拟串口

例程&#xff1a;STM32USBdevice: 基于STM32的USB设备例子程序 - Gitee.com 本篇为USB虚拟串口教程&#xff0c;没有知识&#xff0c;全是实操&#xff0c;按照步骤就能获得一个STM32的USB虚拟串口。本例子是在野火F103MINI开发板上验证的&#xff0c;如果代码中出现一些外设的…...

ubuntu上python setup.py install报错:error: expected initializer before ‘__s128’

问题场景&#xff1a;安装torchsparse时候执行python setup.py install 报错&#xff1a; /usr/include/linux/types.h:12:27: error: expected initializer before ‘__s128’12 | typedef __signed__ __int128 __s128 __attribute__((aligned(16)));| …...

解锁.NET Standard库:从0到1的创建与打包秘籍

一、引言 在当今的软件开发领域&#xff0c;跨平台开发已成为一种趋势。随着不同操作系统和设备的多样化&#xff0c;开发人员需要确保他们的代码能够在多个平台上运行&#xff0c;以满足更广泛的用户需求。.NET Standard 库应运而生&#xff0c;它定义了一组公共 API&#xf…...

Mac 查看 Java SDK 和 Android SDK 的路径

1. Mac 如何查看 JavaSDK的路径 /usr/libexec/java_home -V2. Mac 如何查看 Android SDK 的路径 在 Android Studio 中按 cmd,打开设置&#xff0c;然后如下方式&#xff0c;第三步如果有值就是第三步的信息。 第三步如果没有值&#xff0c;点开Edit&#xff0c;值在下方&…...

6. 马科维茨资产组合模型+政策意图AI金融智能体(DeepSeek-V3)增强方案(理论+Python实战)

目录 0. 承前1. 幻方量化 & DeepSeek1.1 What is 幻方量化1.2 What is DeepSeek 2. 重写AI金融智能体函数3. 汇总代码4. 反思4.1 不足之处4.2 提升思路 5. 启后 0. 承前 本篇博文是对上一篇文章&#xff0c;链接: 5. 马科维茨资产组合模型政策意图AI金融智能体(Qwen-Max)增…...

freeswtch目录下modules.conf各个模块的介绍【freeswitch版本1.6.8】

应用模块&#xff08;applications&#xff09; mod_abstraction&#xff1a; 为其他模块提供抽象层&#xff0c;有助于简化模块开发&#xff0c;让开发者能在统一框架下开发新功能&#xff0c;减少与底层系统的直接交互&#xff0c;提高代码可移植性和可维护性。 mod_av&#…...

Spark/Kafka

文章目录 项目地址一、Spark1. RDD1.1 五大核心属性1.2 执行原理1.3 四种创建方式二、Kafka2.1 生产者(1)分区器(2)生产者提高吞吐量(3) 生产者数据可靠性数据传递语义幂等性和事务数据有序2.2 Broker(1)Broker工作流程(2)节点服役和退役2.3 副本(1)Follower故障细…...

【Linux】华为服务器使用U盘安装统信操作系统

目录 一、准备工作 1.1 下载UOS官方系统 &#xff11;.&#xff12;制作启动U盘 1.3 服务器智能管理系统iBMC 二、iBMC设置U盘启动 一、准备工作 1.1 下载UOS官方系统 服务器CPU的架构是x86-64还是aarch64&#xff09;,地址&#xff1a;统信UOS生态社区 - 打造操作系统创…...

数据库性能优化(sql优化)_SQL执行计划02_yxy

数据库性能优化_SQL执行计划详解02 常用操作符解读1.1 表扫描类型操作符1.1.1 CSCN 聚集索引扫描1.1.2 CSEK 聚集索引数据定位1.1.3 SSEK 二级索引数据定位1.1.4 SSCN 直接使用二级索引进行扫描1.2 其他常见操作符1.2.1 BLKUP 二次扫描1.2.2 SLCT 选择1.2.3 PRJT 投影1.2.4 NSE…...

02.05、链表求和

02.05、[中等] 链表求和 1、题目描述 给定两个用链表表示的整数&#xff0c;每个节点包含一个数位。 这些数位是反向存放的&#xff0c;也就是个位排在链表首部。 编写函数对这两个整数求和&#xff0c;并用链表形式返回结果。 2、解题思路 本题要求对两个链表表示的整数…...

FPGA实现光纤通信(3)——光纤8b/10b编码数据回环

前言 光纤通信属于高速串行通信,具有较高的数据传输速率,通常用于服务器以及通信设备之间用于高速数据交换,对于xilinx 7系列的FPGA,内部具有集成的高速接口用于实现光纤通信。本次就来实现8b/10b编码数据回环。 测试环境:vivado版本:2020.02 FPGA芯片:XC7K70T 测试说…...

Python!从0开始学爬虫:(一)HTTP协议 及 请求与响应

前言 爬虫需要基础知识&#xff0c;HTTP协议只是个开始&#xff0c;除此之外还有很多&#xff0c;我们慢慢来记录。 今天的HTTP协议&#xff0c;会有助于我们更好的了解网络。 一、什么是HTTP协议 &#xff08;1&#xff09;定义 HTTP&#xff08;超文本传输协议&#xff…...

神经网络基础详解

神经元结构 在探讨神经网络的基础时,神经元结构是一个关键概念。神经元是神经网络的基本组成单元,模拟了生物神经元的功能。其结构包括: 细胞体 :负责处理和整合输入信息 树突 :接收来自其他神经元的输入信号 轴突 :将处理后的信息传递给其他神经元 神经元通过加权求和和…...

使用Chrome和Selenium实现对Superset等私域网站的截图

最近遇到了一个问题&#xff0c;因为一些原因&#xff0c;我搭建的一个 Superset 的 Report 功能由于节假日期间不好控制邮件的发送&#xff0c;所以急需一个方案来替换掉 Superset 的 Report 功能 首先我们需要 Chrome 浏览器和 Chrome Driver&#xff0c;这是执行数据抓取的…...

2025展望:“安全计算”平价时代加速到来,数据流通产业兴起

大数据产业创新服务媒体 ——聚焦数据 改变商业 2024年&#xff0c;数据要素产业元年开启。 这是建章立制的一年&#xff1a;从年初《“数据要素”三年行动计划&#xff08;2024—2026年&#xff09;》开始&#xff0c;这一年政策密集出台&#xff0c;涵盖公共数据资源开发利用…...

达梦拷贝DM_HOME的复制安装

近期一个项目需求&#xff0c;需要在没有安装包的情况下&#xff0c;将达梦数据库安装到虚机上&#xff08;生产机上安装了达梦&#xff09;&#xff0c;故采用直接打包生产机DM_HOME的方式拷贝至虚机&#xff0c;再依次执行达梦的部分指令完成安装。以下为验证的步骤&#xff…...

九、CSS工程化方案

一、PostCSS介绍 二、PostCSS插件的使用 项目安装 - npm install postcss-cli 全局安装 - npm install postcss-cli -g postcss-cli地址&#xff1a;GitHub - postcss/postcss-cli: CLI for postcss postcss地址&#xff1a;GitHub - postcss/postcss: Transforming styles…...

二叉树的最大深度(C语言详解版)

一、摘要 嗨喽呀大家&#xff0c;leetcode每日一题又和大家见面啦&#xff0c;今天要讲的是104.二叉树的最大深度&#xff0c;思路互相学习&#xff0c;有什么不足的地方欢迎指正&#xff01;好啦让我们开始吧&#xff01;&#xff01;&#xff01; 二、题目简介 给定一个二…...

深入探索imi框架:PHP Swoole的高性能协程应用实践

摘要 本文将介绍 imi 框架&#xff0c;这是一个基于 PHP Swoole 的高性能协程应用开发框架。imi 支持 HttpApi、WebSocket、TCP 和 UDP 等多种服务类型&#xff0c;利用 Swoole 的优化技术&#xff0c;使得在处理请求时响应速度远超传统的 php-fpm 方式。通过丰富的代码示例&a…...

机器学习-线性回归(参数估计之经验风险最小化)

给定一组包含 &#x1d441; 个训练样本的训练集 我们希望能够 学习一个最优的线性回归的模型参数 &#x1d498; 现在我们来介绍线性回归的一种模型参数估计方法&#xff1a;经验风险最小化。 我们前面说过&#xff0c;对于标签 &#x1d466; 和模型输出都为连续的实数值&…...

使用 Elasticsearch 导航检索增强生成图表

作者&#xff1a;来自 Elastic Louis Jourdain 及 Ivan Monnier 了解如何使用知识图谱来增强 RAG 结果&#xff0c;同时在 Elasticsearch 中高效存储图谱。本指南探讨了根据用户查询动态生成知识子图的详细策略。 检索增强生成 (RAG) 通过将大型语言模型 (LLM) 的输出基于事实数…...

Flutter调用HarmonyOS NEXT原生相机拍摄相册选择照片视频

目录 1.项目背景 2.遇到的问题 3.开发准备 4.开发过程 首先创建注册调用鸿蒙原生的渠道 创建并初始化插件 绑定通道完成插件中的功能 5.具体步骤 根据传值判断是相册选取还是打开相机 相册选取照片或视频 相机拍摄照片或视频 调用picker拍摄接口获取拍摄的结果 视频…...

浅析云场景SSD实时迁移技术

在数据中心的运营管理中&#xff0c;负载均衡和系统容错是确保高效稳定运行的关键。SSD实时迁移技术&#xff0c;为解决这些问题提供了创新方案&#xff0c;成为数据中心技术发展的重要驱动力。 以AI训练任务为例&#xff0c;其运行时间长且无需用户频繁交互。数据中心的负载会…...

WordPress Hunk Companion插件节点逻辑缺陷导致Rce漏洞复现(CVE-2024-9707)(附脚本)

免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 0x0…...

BGP分解实验·11——路由聚合与条件性通告(3)

续接上&#xff08;2&#xff09;的实验。其拓扑如下&#xff1a; 路由聚合的负向也就是拆分&#xff0c;在有双出口的情况下&#xff0c;在多出口做流量分担是优选方法之一。 BGP可以根据指定来源而聚合路由&#xff0c;在产生该聚合路由的范围内的条目注入到本地BGP表后再向…...

SQL Server 使用SELECT INTO实现表备份

在数据库管理过程中&#xff0c;有时我们需要对表进行备份&#xff0c;以防数据丢失或修改错误。在 SQL Server 中&#xff0c;可以使用 SELECT INTO 语句将数据从一个表备份到另一个表。 备份表的 SQL 语法&#xff1a; SELECT * INTO 【备份表名】 FROM 【要备份的表】 SEL…...

RPC是什么?和HTTP区别?

RPC 是什么&#xff1f;HTTP 是什么&#xff1f; 作为一个程序员&#xff0c;假设我们需要从A电脑的进程发送一段数据到B电脑的进程&#xff0c;我们一般会在代码中使用 Socket 进行编程。 此时&#xff0c;可选性一般就是 TCP 和 UDP 二选一&#xff0c;由于 TCP 可靠、UDP 不…...

西藏酥油茶:高原上的醇香温暖

西藏酥油茶:高原上的醇香温暖 在西藏高原,有一种饮品,它不仅滋养了一代又一代的藏民,还承载着丰富的文化与历史,它就是西藏酥油茶。酥油茶,藏语称为“恰苏玛”,意为搅动的茶,是藏族人民日常生活中不可或缺的一部分,更是待客、祭祀等活动中的重要礼仪物品。 历史与文化渊源 酥…...

十、VUE中的CSS

一、vue中解决样式不冲突的两种方式 scoped方式 在App.vue中引入Helloworld子组件 在Helloworld子组件中再次引入我们编写Demo子组件 解释&#xff1a; 这种方式是在style上加了个scoped,限制了样式的使用范围。 动态类名方式 二、vue构建打包 npm run build...

论文阅读 AlphaFold 2

用AlphaFold进行非常精确的蛋白质结构的预测(AlphaFold2) 发表于2021年07月15日 NatureDOI: 10.1038/s41586-021-03819-2自然和科学杂志评选为2021年最重要的科学突破之一2021年AI在科学界最大的突破 前言 2020年11月30号, deepmind博客说AlphaFold解决了50年以来生物学的大挑…...

PVE 虚拟机安装 Debian 无图形化界面服务器

Debian 安装 Debian 镜像下载 找一个Debian镜像服务器&#xff0c;根据需要的版本和自己硬件选择。 iso-cd/&#xff1a;较小&#xff0c;仅包含安装所需的基础组件&#xff0c;可能需要网络访问来完成安装。有镜像 debian-12.9.0-amd64-netinst.isoiso-dvd/&#xff1a;较…...