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 混合持久化的流程
混合持久化的基本流程
- 判断是否开启 AOF 持久化:如果 Redis 配置中开启了 AOF 持久化,Redis 会继续执行混合持久化的后续流程;如果未开启 AOF,Redis 会直接加载 RDB 文件进行恢复。
- 检查 appendonly.aof 文件是否存在:
如果 AOF 文件存在,Redis 会继续执行混合持久化恢复流程。
如果 AOF 文件不存在,Redis 会直接加载 RDB 文件进行恢复。 - 判断 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个特征
- 内存存储
- 单线程
- 多路i/o复用
- 数据结构
内存存储:
内存访问速度:内存是计算机中 最快的存储介质,其读取速度和写入速度非常高,通常在纳秒级别(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,它是一个基于内存的 NoSQL(非关系型)数据库,数据以 键值对 存储,支持各种复杂的数据结构 为什么会出现 Redis? 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,选择版本后点击“install”执行安装...
Java 设计模式 二 单例模式 (Singleton Pattern)
单例模式 (Singleton Pattern) 是一种常见的设计模式,属于创建型模式。它的核心思想是确保一个类只有一个实例,并提供一个全局访问点来获取该实例。通常用于那些需要全局控制的场景,比如配置管理、日志系统、数据库连接池等。 1. 单例模式的…...
golang网络编程
socket编程 socket图解 Socket是BSD UNIX的进程通信机制,通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄。Socket可以理解为TCP/IP网络的API,它定义了许多函数或例程,程序员可以用它们来开发TCP/IP网…...
kotlin内联函数——takeIf和takeUnless
1.takeIf 当对一个对象调用takeIf时,如果对象满足给定的判断条件,则返回该对象;否则,返回null。因此,takeIf是对单个对象进行过滤的函数。例如, class User {var name: String? nullvar age 99fun set…...
计算机网络 (54)系统安全:防火墙与入侵检测
前言 计算机网络系统安全是确保网络通信和数据不受未经授权访问、泄露、破坏或篡改的关键。防火墙和入侵检测系统(IDS)是维护网络系统安全的两大核心组件。 一、防火墙 定义与功能 防火墙是一种用来加强网络之间访问控制的特殊网络互联设备,它…...
第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
矩阵置零:1. 开两个数组判断该行/该列是否有0;2. 用第0行/第0列分别判断该列/该行是否有0 螺旋矩阵:记录方向,一直按某方向前进,遇到障碍方向就变一下 1. 矩阵置零 给定一个 *m* x *n* 的矩阵,如果一个元…...
量子编程语言:Qiskit 与 Cirq
在量子计算的领域,开发者已经可以使用一些专门为量子计算设计的编程语言和框架。其中,Qiskit 和 Cirq 是两个非常流行的选择,它们为不同的量子计算机提供编程接口,帮助开发者理解量子电路的设计和执行。 1. Qiskit Qiskit 是 IBM…...
leetcode 124. 二叉树中的最大路径和
题目:124. 二叉树中的最大路径和 - 力扣(LeetCode) 定义一个节点的“最大单向路径和”是single,single有以下几种情况: 只有该节点该节点左儿子的single该节点右儿子的single 设答案是节点 node 为根节点࿰…...
程序员转型测试:解锁漏洞挖掘新旅程
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 程序…...
基于Springboot用axiospost请求接收字符串参数为null的解决方案
问题 今天在用前端 post 请求后端时发现,由于是以 Json对象的形式传输的,后端用两个字符串形参无法获取到对应的参数值 前端代码如下: 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绘图和深度学习中,涉及了多个复杂的概念和技术,这些技术在图像生成、训练加速以及多模态学习等方面起着至关重要的作用。在这篇博客中,我们将讨论几个关键概念&…...
警企联动齐发力、共筑反诈“防护墙”
2025年1月10日是第五个中国人民警察节,南通移动联合南通公安反诈中心,深入社区商圈,开展防范电信网络诈骗宣传活动,进一步增强广大人民群众的反诈意识和能力,全力守护好群众的“钱袋子”。 当日,活动现场一大早就呈现出一片忙碌景象,工作人员支起摊位,将各类精心制作的反诈宣传…...
Node.js HTTP模块详解:创建服务器、响应请求与客户端请求
Node.js HTTP模块详解:创建服务器、响应请求与客户端请求 Node.js 的 http 模块是 Node.js 核心模块之一,它允许你创建 HTTP 服务器和客户端。以下是一些关键知识点和代码示例: 1. 创建 HTTP 服务器 使用 http.createServer() 方法可以创建…...
Alibaba Spring Cloud 十七 Sentinel熔断降级
概述 在微服务架构中,熔断与降级是保证系统稳定性的重要机制,能有效防止故障蔓延或雪崩效应。当某个服务出现异常、延迟过高或错误率过高时,触发熔断保护,将该服务“隔离”一段时间,避免影响整体系统的吞吐和可用性。 …...
linux——网络基础
文章目录 目录 文章目录 踏入网络世界:探索 Linux 网络的无垠天地 一、网络发展 早期单机处理模式 网络发展的需求催生 网络发展后的优势对比 二、局域网or广域网 典型局域网架构 广域网连接多个局域网 二者关系 三、协议 语言层与汉语协议 通信设备层与电话机协议 …...
Spring Boot 集成 WebClient 实战教程 实现同步、异步请求处理以及响应式编程、响应式流、响应式Mono
该项目介绍springboot集成WebClient 实现服务的请求操作 示例中演示了,如何配置WebClient的请求头,请求参数等相关参数,实现同步、异步请求处理以及响应式编程、响应式流、响应式Mono。 为什么使用WebClient 不用RestTemplate 在 Spring Framework 5.0 及更高版本中,Res…...
健身房项目 Uniapp+若依Vue3版搭建!!
本次系统实现主要负责前端前端功能的实现。其中系统前端主要分为三大部分,首页,教练列表页,我的页面。 首页 首页的实现效果如图 1.会员卡组件 首页的Vip会员卡部分,团课活动的DataPicker,团课选择都采用了组件化封…...
(2)STM32 USB设备开发-USB虚拟串口
例程:STM32USBdevice: 基于STM32的USB设备例子程序 - Gitee.com 本篇为USB虚拟串口教程,没有知识,全是实操,按照步骤就能获得一个STM32的USB虚拟串口。本例子是在野火F103MINI开发板上验证的,如果代码中出现一些外设的…...
ubuntu上python setup.py install报错:error: expected initializer before ‘__s128’
问题场景:安装torchsparse时候执行python setup.py install 报错: /usr/include/linux/types.h:12:27: error: expected initializer before ‘__s128’12 | typedef __signed__ __int128 __s128 __attribute__((aligned(16)));| …...
解锁.NET Standard库:从0到1的创建与打包秘籍
一、引言 在当今的软件开发领域,跨平台开发已成为一种趋势。随着不同操作系统和设备的多样化,开发人员需要确保他们的代码能够在多个平台上运行,以满足更广泛的用户需求。.NET Standard 库应运而生,它定义了一组公共 API…...
Mac 查看 Java SDK 和 Android SDK 的路径
1. Mac 如何查看 JavaSDK的路径 /usr/libexec/java_home -V2. Mac 如何查看 Android SDK 的路径 在 Android Studio 中按 cmd,打开设置,然后如下方式,第三步如果有值就是第三步的信息。 第三步如果没有值,点开Edit,值在下方&…...
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. 承前 本篇博文是对上一篇文章,链接: 5. 马科维茨资产组合模型政策意图AI金融智能体(Qwen-Max)增…...
freeswtch目录下modules.conf各个模块的介绍【freeswitch版本1.6.8】
应用模块(applications) mod_abstraction: 为其他模块提供抽象层,有助于简化模块开发,让开发者能在统一框架下开发新功能,减少与底层系统的直接交互,提高代码可移植性和可维护性。 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官方系统 1.2制作启动U盘 1.3 服务器智能管理系统iBMC 二、iBMC设置U盘启动 一、准备工作 1.1 下载UOS官方系统 服务器CPU的架构是x86-64还是aarch64),地址:统信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、题目描述 给定两个用链表表示的整数,每个节点包含一个数位。 这些数位是反向存放的,也就是个位排在链表首部。 编写函数对这两个整数求和,并用链表形式返回结果。 2、解题思路 本题要求对两个链表表示的整数…...
FPGA实现光纤通信(3)——光纤8b/10b编码数据回环
前言 光纤通信属于高速串行通信,具有较高的数据传输速率,通常用于服务器以及通信设备之间用于高速数据交换,对于xilinx 7系列的FPGA,内部具有集成的高速接口用于实现光纤通信。本次就来实现8b/10b编码数据回环。 测试环境:vivado版本:2020.02 FPGA芯片:XC7K70T 测试说…...
Python!从0开始学爬虫:(一)HTTP协议 及 请求与响应
前言 爬虫需要基础知识,HTTP协议只是个开始,除此之外还有很多,我们慢慢来记录。 今天的HTTP协议,会有助于我们更好的了解网络。 一、什么是HTTP协议 (1)定义 HTTP(超文本传输协议ÿ…...
神经网络基础详解
神经元结构 在探讨神经网络的基础时,神经元结构是一个关键概念。神经元是神经网络的基本组成单元,模拟了生物神经元的功能。其结构包括: 细胞体 :负责处理和整合输入信息 树突 :接收来自其他神经元的输入信号 轴突 :将处理后的信息传递给其他神经元 神经元通过加权求和和…...
使用Chrome和Selenium实现对Superset等私域网站的截图
最近遇到了一个问题,因为一些原因,我搭建的一个 Superset 的 Report 功能由于节假日期间不好控制邮件的发送,所以急需一个方案来替换掉 Superset 的 Report 功能 首先我们需要 Chrome 浏览器和 Chrome Driver,这是执行数据抓取的…...
2025展望:“安全计算”平价时代加速到来,数据流通产业兴起
大数据产业创新服务媒体 ——聚焦数据 改变商业 2024年,数据要素产业元年开启。 这是建章立制的一年:从年初《“数据要素”三年行动计划(2024—2026年)》开始,这一年政策密集出台,涵盖公共数据资源开发利用…...
达梦拷贝DM_HOME的复制安装
近期一个项目需求,需要在没有安装包的情况下,将达梦数据库安装到虚机上(生产机上安装了达梦),故采用直接打包生产机DM_HOME的方式拷贝至虚机,再依次执行达梦的部分指令完成安装。以下为验证的步骤ÿ…...
九、CSS工程化方案
一、PostCSS介绍 二、PostCSS插件的使用 项目安装 - npm install postcss-cli 全局安装 - npm install postcss-cli -g postcss-cli地址:GitHub - postcss/postcss-cli: CLI for postcss postcss地址:GitHub - postcss/postcss: Transforming styles…...
二叉树的最大深度(C语言详解版)
一、摘要 嗨喽呀大家,leetcode每日一题又和大家见面啦,今天要讲的是104.二叉树的最大深度,思路互相学习,有什么不足的地方欢迎指正!好啦让我们开始吧!!! 二、题目简介 给定一个二…...
深入探索imi框架:PHP Swoole的高性能协程应用实践
摘要 本文将介绍 imi 框架,这是一个基于 PHP Swoole 的高性能协程应用开发框架。imi 支持 HttpApi、WebSocket、TCP 和 UDP 等多种服务类型,利用 Swoole 的优化技术,使得在处理请求时响应速度远超传统的 php-fpm 方式。通过丰富的代码示例&a…...
机器学习-线性回归(参数估计之经验风险最小化)
给定一组包含 𝑁 个训练样本的训练集 我们希望能够 学习一个最优的线性回归的模型参数 𝒘 现在我们来介绍线性回归的一种模型参数估计方法:经验风险最小化。 我们前面说过,对于标签 𝑦 和模型输出都为连续的实数值&…...
使用 Elasticsearch 导航检索增强生成图表
作者:来自 Elastic Louis Jourdain 及 Ivan Monnier 了解如何使用知识图谱来增强 RAG 结果,同时在 Elasticsearch 中高效存储图谱。本指南探讨了根据用户查询动态生成知识子图的详细策略。 检索增强生成 (RAG) 通过将大型语言模型 (LLM) 的输出基于事实数…...
Flutter调用HarmonyOS NEXT原生相机拍摄相册选择照片视频
目录 1.项目背景 2.遇到的问题 3.开发准备 4.开发过程 首先创建注册调用鸿蒙原生的渠道 创建并初始化插件 绑定通道完成插件中的功能 5.具体步骤 根据传值判断是相册选取还是打开相机 相册选取照片或视频 相机拍摄照片或视频 调用picker拍摄接口获取拍摄的结果 视频…...
浅析云场景SSD实时迁移技术
在数据中心的运营管理中,负载均衡和系统容错是确保高效稳定运行的关键。SSD实时迁移技术,为解决这些问题提供了创新方案,成为数据中心技术发展的重要驱动力。 以AI训练任务为例,其运行时间长且无需用户频繁交互。数据中心的负载会…...
WordPress Hunk Companion插件节点逻辑缺陷导致Rce漏洞复现(CVE-2024-9707)(附脚本)
免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 0x0…...
BGP分解实验·11——路由聚合与条件性通告(3)
续接上(2)的实验。其拓扑如下: 路由聚合的负向也就是拆分,在有双出口的情况下,在多出口做流量分担是优选方法之一。 BGP可以根据指定来源而聚合路由,在产生该聚合路由的范围内的条目注入到本地BGP表后再向…...
SQL Server 使用SELECT INTO实现表备份
在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SELECT INTO 语句将数据从一个表备份到另一个表。 备份表的 SQL 语法: SELECT * INTO 【备份表名】 FROM 【要备份的表】 SEL…...
RPC是什么?和HTTP区别?
RPC 是什么?HTTP 是什么? 作为一个程序员,假设我们需要从A电脑的进程发送一段数据到B电脑的进程,我们一般会在代码中使用 Socket 进行编程。 此时,可选性一般就是 TCP 和 UDP 二选一,由于 TCP 可靠、UDP 不…...
西藏酥油茶:高原上的醇香温暖
西藏酥油茶:高原上的醇香温暖 在西藏高原,有一种饮品,它不仅滋养了一代又一代的藏民,还承载着丰富的文化与历史,它就是西藏酥油茶。酥油茶,藏语称为“恰苏玛”,意为搅动的茶,是藏族人民日常生活中不可或缺的一部分,更是待客、祭祀等活动中的重要礼仪物品。 历史与文化渊源 酥…...
十、VUE中的CSS
一、vue中解决样式不冲突的两种方式 scoped方式 在App.vue中引入Helloworld子组件 在Helloworld子组件中再次引入我们编写Demo子组件 解释: 这种方式是在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镜像服务器,根据需要的版本和自己硬件选择。 iso-cd/:较小,仅包含安装所需的基础组件,可能需要网络访问来完成安装。有镜像 debian-12.9.0-amd64-netinst.isoiso-dvd/:较…...