南昌市网络开发公司_简单html网页制作代码_中层管理者培训课程有哪些_重庆关键词优化服务
2025/10/14 9:55:51
来源:https://blog.csdn.net/weixin_41545189/article/details/147023475
浏览:
次
关键词:南昌市网络开发公司_简单html网页制作代码_中层管理者培训课程有哪些_重庆关键词优化服务
南昌市网络开发公司_简单html网页制作代码_中层管理者培训课程有哪些_重庆关键词优化服务
- 什么是缓存穿透?怎么解决?
- 问题解释:缓存穿透是指客户端请求的数据在缓存中不存在,并且在数据库中也不存在 ,导致请求直接打到数据库上。比如用户一直请求一个不存在的商品 ID 对应的商品信息,缓存没命中就查数据库,数据库也没有,每次都给数据库造成无效压力。
- 解决方法:对空结果也进行缓存,设置较短过期时间,防止占用过多缓存空间;使用布隆过滤器,在请求访问数据库前,先判断数据是否可能存在,不存在就直接返回,避免数据库压力。
- 你能介绍一下布隆过滤器吗?
- 解释:布隆过滤器是一种概率型数据结构,用于判断一个元素是否可能存在于集合中。它通过多个哈希函数将元素映射到一个位数组上,占用空间小。但它有一定误判率,即可能会把不存在的元素判断为存在,但不会把存在的元素判断为不存在 。比如判断一个邮箱地址是否在垃圾邮件列表中,可以用布隆过滤器快速筛一下。
- 什么是缓存击穿?怎么解决?
- 问题解释:缓存击穿是指某个热点数据(高并发访问的数据)在缓存中过期的瞬间,大量请求同时涌入,直接访问数据库,造成数据库压力过大。比如秒杀活动时,秒杀商品的信息缓存过期那刻,大量请求会直接到数据库查询商品信息。
- 解决方法:对热点数据设置永不过期;或者在缓存过期时,使用互斥锁(如 Redis 的 SETNX 命令),只允许一个线程去数据库加载数据并更新缓存,其他线程等待,拿到锁的线程更新完缓存后,释放锁,其他线程再从缓存中获取数据。
- 什么是缓存雪崩?怎么解决?
- 问题解释:缓存雪崩是指在某一时刻,大量缓存同时失效,导致大量请求直接涌入数据库,使数据库负载过高甚至崩溃。比如缓存服务器重启,或者大量缓存设置了相同的过期时间,到期同时失效。
- 解决方法:给缓存设置不同的过期时间,避免集中失效;使用多级缓存,不同级别的缓存设置不同过期时间;搭建缓存集群,增加缓存的可用性和稳定性,防止单点故障。
- redis 做为缓存,mysql 的数据如何与 redis 进行同步呢?(双写一致性)
- 解决方法:先更新数据库,成功后再更新 Redis;或者先删除 Redis 缓存,再更新数据库,后续请求过来时,发现 Redis 没有数据,会重新从数据库读取并更新到 Redis。但这两种方式都有一定缺陷,比如先更新数据库再更新 Redis,在高并发下可能出现更新顺序错乱问题;先删缓存再更新数据库,在删缓存后、更新数据库前有其他请求过来,会读到旧数据。可以通过消息队列等方式来保证最终一致性,比如更新数据库后,往消息队列发送消息,消费者收到消息后去更新 Redis。
- 那这个排他锁是如何保证读写、读读互斥的呢?
- 解释:排他锁(写锁)主要保证写操作的互斥性。在写操作时,获取排他锁,此时其他写操作和读操作都要等待锁释放。读读不互斥,因为读操作不会修改数据,多个读操作同时进行不会影响数据一致性。而在 Redis 中,使用 SETNX 等命令实现类似排他锁功能,在写操作前尝试设置锁,设置成功则进行写操作,其他请求发现锁已被设置就等待。
- 你听说过延时双删吗?为什么不用它呢?
- 解释:延时双删是一种处理缓存和数据库一致性的策略。先删除缓存,更新数据库,然后等待一段时间后再删除一次缓存。等待的这段时间是为了确保在更新数据库期间,其他读请求从数据库读到新数据后更新到缓存中,第二次删除缓存是防止在等待时间内有其他写请求修改了数据库,而缓存没更新。
- 不用原因:延时时间不好确定,设置短了可能达不到效果,设置长了影响系统性能;而且即使使用延时双删,在高并发下也不能完全保证数据一致性,实现复杂且效果有限。
- redis 做为缓存,mysql 的数据如何与 redis 进行同步呢?(双写一致性)
- 同第 5 题:可以先更新数据库,再更新 Redis,但要注意高并发下的顺序问题;也可以先删除 Redis 缓存,再更新数据库,后续请求重新读取数据库数据更新到 Redis;还可以借助消息队列,更新数据库后发消息到队列,消费者接收消息更新 Redis。
- redis 做为缓存,数据的持久化是怎么做的?
- RDB 持久化:在指定时间间隔内将内存中的数据集快照写入磁盘,是一种基于时间点的快照方式。可以手动执行 SAVE 或 BGSAVE 命令,也可以配置自动触发机制,比如在一定时间内有一定数量的写操作就触发。它的优点是恢复速度快,生成的文件小,适合大规模数据恢复。缺点是可能丢失最后一次快照到发生故障期间的数据。
- AOF 持久化:以追加的方式记录服务器所处理的每一个写命令,当 Redis 重启时会重新执行这些命令来恢复数据。可以通过配置文件设置不同的刷盘策略,如每秒刷盘、每次写操作都刷盘等。优点是数据完整性好,最多丢失一秒的数据(每秒刷盘策略下)。缺点是文件体积大,恢复速度相对 RDB 慢。
- 这两种持久化方式有什么区别呢?
- 数据完整性:AOF 更完整,最多丢失一秒(每秒刷盘)或不丢失(每次写操作刷盘);RDB 可能丢失最后一次快照后的所有数据。
- 文件体积:AOF 文件通常比 RDB 大,因为它记录每一个写命令。
- 恢复速度:RDB 恢复速度快,直接加载快照文件;AOF 要重放写命令,恢复较慢。
- 性能影响:RDB 对性能影响小,只有在生成快照时会有短暂阻塞;AOF 根据刷盘策略不同,对性能有不同程度影响,每次写操作都刷盘性能影响较大。
- 这两种方式,哪种恢复的比较快呢?
- 答案:RDB 恢复比较快。因为 RDB 是基于快照,直接将保存的内存数据集快照加载到内存中就可以恢复数据。而 AOF 需要重新执行记录的写命令来重建数据,执行命令需要时间,所以恢复速度相对较慢。
- Redis 的数据过期策略有哪些?
- 定时删除:在设置键过期时间的同时,创建一个定时器,当过期时间到达时,立即执行对键的删除操作。优点是能及时释放内存,但对 CPU 不友好,大量键同时过期时,会占用较多 CPU 资源。
- 惰性删除:键过期后不会立即删除,而是在客户端访问该键时,检查键是否过期,如果过期则删除。优点是节约 CPU 资源,缺点是可能导致过期键长时间占用内存,浪费空间。
- 定期删除:每隔一段时间,对数据库中的键进行一次检查,随机抽查一部分键,删除其中过期的键。是定时删除和惰性删除的折中方案,通过控制检查频率和抽查数量,平衡 CPU 时间和内存空间。
- Redis 的数据淘汰策略有哪些?
- volatile-lru(最近最少使用):从设置了过期时间的键中,淘汰掉最近最少使用的键。
- volatile-ttl:从设置了过期时间的键中,淘汰剩余过期时间最短的键。
- volatile-random:从设置了过期时间的键中,随机淘汰键。
- allkeys-lru:从所有键中(无论是否设置过期时间),淘汰最近最少使用的键。
- allkeys-random:从所有键中,随机淘汰键。
- noeviction:不进行淘汰,当内存不足时,新的写请求会返回错误,只读操作可以正常执行。
- 数据库有 1000 万数据,Redis 只能缓存 20w 数据。如何保证 Redis 中的数据都是热点数据?
- 使用 LRU 策略:在 Redis 配置中选择 allkeys-lru 或 volatile-lru 淘汰策略。allkeys-lru 从所有键中淘汰最近最少使用的,volatile-lru 从设置过期时间的键中淘汰。这样系统会自动把长时间不访问的非热点数据淘汰掉,保留经常被访问的热点数据。
- 业务逻辑筛选:在应用程序层面,根据业务规则提前判断哪些数据是热点数据,比如访问频率高的商品信息、用户常用的配置信息等,优先将这些数据存入 Redis。
- 定期统计分析:定期统计数据的访问频率,将访问频率低的数据从 Redis 中剔除,补充新的热点数据。可以通过日志记录访问情况,然后进行分析处理。
- Redis 的内存用完了会发生什么?
- 如果采用 noeviction 策略:新的写操作会返回错误,客户端无法写入新数据,但读操作可以正常进行。比如执行 SET 命令添加新键值对会失败,但 GET 命令获取已存在数据正常。
- 如果采用其他淘汰策略(如 lru、random 等):当新数据要写入且内存不足时,会按照相应的淘汰策略(如淘汰最近最少使用的键等)删除部分旧数据,为新数据腾出空间,然后新数据写入操作可以继续进行。
- Redis 分布式锁如何实现?
- 使用 SET 命令实现:利用 Redis 的 SET 命令,通过设置一个唯一的键值对,并且设置过期时间(防止死锁)来模拟锁。例如使用
SET lock_key unique_value NX PX 30000
,其中 NX
表示只有键不存在时才设置成功(即获取锁成功),PX 30000
表示设置键的过期时间为 30 秒。当一个客户端成功设置这个键值对时,就相当于获取了锁,其他客户端设置失败则等待或重试。操作完成后,通过 DEL 命令删除这个键值对来释放锁。 - 使用 Redisson 框架:它对 Redis 分布式锁进行了封装,提供了更便捷的 API。通过创建 RedissonClient 连接 Redis,然后使用
RLock lock = redisson.getLock("myLock");
获取锁对象,lock.lock();
加锁,lock.unlock();
解锁,内部实现了自动续期等功能,避免锁过期业务未完成的问题。
- 那如何控制 Redis 实现分布式锁的有效时长呢?
- 设置过期时间:在使用 SET 命令实现分布式锁时,通过
PX
或 EX
参数设置键的过期时间。如 SET lock_key unique_value NX PX 5000
,表示设置锁的过期时间为 5000 毫秒(5 秒),5 秒后即使没有手动释放锁,Redis 也会自动删除这个键,相当于释放了锁。 - 使用 Redisson 等框架:以 Redisson 为例,它提供了更灵活的方式。可以在加锁时设置锁的 leaseTime(租约时间),如
lock.lock(10, TimeUnit.SECONDS);
表示锁的有效时长为 10 秒,并且在业务执行过程中,如果发现锁快过期了,框架会自动续期,保证业务执行期间锁不会失效。
- Redisson 实现的分布式锁是可重入的吗?
- 答案:Redisson 实现的分布式锁是可重入的。可重入锁是指同一个线程在持有锁的情况下,可以再次获取该锁而不会产生死锁。Redisson 内部通过对获取锁的线程进行标识,当同一个线程再次请求获取相同的锁时,会增加锁的持有计数,而不是阻塞等待,释放锁时也是根据持有计数来逐步释放,直到计数为 0 才真正释放锁。
- Redisson 实现的分布式锁能解决主从一致性的问题吗?
- 答案:Redisson 实现的分布式锁在一定程度上缓解主从一致性问题,但不能完全解决。在 Redis 主从架构下,当主节点获取锁后,数据同步到从节点有一定延迟,此时如果主节点故障,从节点升为主节点,可能会出现锁的不一致情况。Redisson 通过一些机制如看门狗自动续期等,尽量保证在主从切换等场景下锁的可用性和一致性,但由于 Redis 主从复制本身的异步特性,无法做到绝对的主从一致性。
- 如果业务非要保证数据的强一致性,这个该怎么解决呢?
- 使用分布式事务:比如基于两阶段提交(2PC)协议来实现分布式事务。在更新 Redis 和数据库时,引入协调者,先让所有参与者(Redis、数据库等)准备操作,都准备成功后,再让所有参与者提交操作。但 2PC 存在性能问题和单点故障风险。也可以使用三阶段提交(3PC)进行改进,增加预提交阶段,降低单点故障影响。
- 基于消息队列:使用可靠的消息队列如 RabbitMQ、Kafka 等。先将数据更新操作封装成消息发送到消息队列,消费者按顺序消费消息,依次更新 Redis 和数据库,通过消息的有序性和可靠投递保证数据的强一致性。同时配合事务消息等机制,确保消息发送和数据库操作的原子性。
- 使用分布式协调器:如 ZooKeeper,它可以提供分布式锁、分布式同步等功能。在更新数据时,先获取 ZooKeeper 的锁,然后依次更新 Redis 和数据库,保证同一时刻只有一个节点能进行数据更新操作,从而保证强一致性。
- Redis 集群有哪些方案,知道吗?
- Redis Sentinel(哨兵):是 Redis 的高可用解决方案。它由一个或多个哨兵节点组成,哨兵节点监控主节点和从节点的状态,当主节点发生故障时,哨兵会自动进行故障转移,将一个从节点提升为主节点,并通知客户端新的主节点地址。它能实现主从切换的自动化,但数据分片功能较弱,主要用于保障高可用性。
- Redis Cluster:是 Redis 官方提供的分布式集群方案。它采用哈希槽(Hash Slot)的方式来管理数据,将整个键空间划分为 16384 个哈希槽,每个节点负责一部分哈希槽。客户端可以直接连接集群中的任意节点,通过哈希算法计算键对应的哈希槽,然后找到负责该哈希槽的节点进行数据操作。它支持数据分片、自动故障转移等功能,能实现大规模数据存储和高并发访问。
- 那你来介绍一下主从同步
- 解释:在 Redis 主从架构中,主节点负责处理写操作和部分读操作,从节点复制主节点的数据。主从同步过程如下:从节点启动后,会向主节点发送 SYNC 命令,主节点收到命令后,会执行 BGSAVE 命令生成 RDB 快照文件,并将快照文件发送给从节点,从节点接收并加载快照文件,恢复数据。之后主节点会将从发送 SYNC 命令开始记录的写命令(写缓冲区中的命令)发送给从节点,从节点执行这些命令,从而与主节点数据保持一致。后续主节点的写操作,会通过异步复制的方式实时发送给从节点执行,保证数据持续同步。
- 能说一下,主从同步数据的流程吗?
- 全量同步:从节点初次连接主节点或与主节点断开重连后,发送 SYNC 命令。主节点执行 BGSAVE 生成 RDB 快照文件,将文件发送给从节点。从节点接收 RDB 文件,清空自身数据并加载 RDB 文件恢复数据。主节点将写缓冲区中从发送 SYNC 命令开始记录的写命令发送给从节点,从节点执行这些命令。
- 增量同步:全量同步完成后,主节点后续产生的写操作命令,会通过异步方式实时发送给从节点,从节点接收到后执行这些命令,保持与主节点数据一致。
- 怎么保证 Redis 的高并发高可用?
- 使用 Redis 集群:如 Redis Cluster,通过哈希槽将数据分布在多个节点上,实现数据分片,能处理大量数据和高并发请求。同时它具备自动故障转移功能,当某个节点故障时,集群会自动将其负责的哈希槽迁移到其他正常节点,保证服务可用性。
- 主从复制结合哨兵:采用主从架构,主节点处理写请求,从节点分担读请求,提高并发能力。再使用 Redis Sentinel 监控主从节点,当主节点故障时,哨兵自动进行故障转移,提升可用性。
- 合理配置参数:调整 Redis 的内存分配、过期策略、淘汰策略等参数。例如根据业务情况设置合适的最大内存,选择合适的内存淘汰策略(如 allkeys-lru),保证在高并发下内存使用合理,不影响性能。
- 优化网络和硬件:使用高速网络设备,减少网络延迟。配置高性能服务器硬件,如高速 CPU、大容量内存、高速磁盘等,提升 Redis 的处理能力。
- 你们使用 Redis 是单点还是集群,哪种集群?
- 单点:如果业务数据量小、并发低,可能使用单点 Redis。它部署简单,所有数据都存储在一个 Redis 实例中,适用于对性能和可用性要求不高的场景。但存在单点故障风险,一旦实例故障,服务就不可用。
- 集群:
- Redis Sentinel 集群:如果更注重高可用性,对数据分片需求不高,可能采用 Redis Sentinel 集群。它由多个哨兵节点监控主从节点,能自动进行主从切换,保障服务的高可用性。
- Redis Cluster 集群:对于数据量大、高并发且需要分布式存储的业务,会使用 Redis Cluster 集群。它通过哈希槽实现数据分片,支持自动故障转移和动态扩容缩容,能更好地应对大规模数据和高并发场景。
- Redis 集群脑裂,该怎么解决呢?
- 问题解释:Redis 集群脑裂是指在网络分区故障时,集群中的部分节点与主节点网络断开,这些节点各自认为自己是主节点,从而导致一个集群中出现多个 “主节点”,客户端的请求会被分散到不同 “主节点”,造成数据不一致等问题 。
- 解决方法:
- 设置合适的参数:调整
min - slaves - to - write
和 min - slaves - max - lag
参数。min - slaves - to - write
表示主节点至少需要有多少个正常的从节点才能执行写操作,min - slaves - max - lag
表示从节点与主节点的最大延迟时间。当主节点发现从节点数量不满足 min - slaves - to - write
或者从节点延迟超过 min - slaves - max - lag
时,主节点会拒绝写操作,这样可以避免在脑裂时,部分主节点继续写数据导致数据不一致。 - 使用外部锁:借助分布式锁(如使用 ZooKeeper 实现的锁),在主节点执行写操作前,先获取分布式锁。在网络分区发生脑裂时,只有一个 “主节点” 能获取到锁,从而只有这个节点能进行写操作,避免数据不一致。
- 优化网络:增强网络的稳定性,减少网络分区故障发生的概率。例如采用冗余网络链路、更好的网络设备等,降低因网络问题导致脑裂的可能性。
- Redis 的分片集群有什么作用?
- 数据扩容:随着业务数据量不断增长,单个 Redis 节点的存储容量可能无法满足需求。分片集群通过将数据分散存储在多个节点上,突破了单机存储的限制,能够轻松应对大规模数据存储的场景。例如,原本单机只能存储 10GB 数据,使用分片集群后,可以通过增加节点扩展到 TB 级甚至更大的存储容量。
- 提高并发处理能力:在高并发场景下,单个节点的处理能力有限。分片集群将请求分散到多个节点上,每个节点处理一部分请求,从而提升了整个集群的并发处理能力。比如,在电商秒杀活动中,大量用户同时请求商品信息,分片集群可以将这些请求分摊到不同节点,避免单个节点因压力过大而崩溃。
- 增强可用性:当集群中某个节点出现故障时,其他节点仍然可以继续提供服务。同时,分片集群具备自动故障转移功能,能够将故障节点上的数据迁移到正常节点,保证服务的连续性,减少因节点故障导致的业务中断时间。
- Redis 分片集群中数据是怎么存储和读取的?
- 数据存储:Redis 分片集群采用哈希槽(Hash Slot)机制。整个键空间被划分为 16384 个哈希槽,每个节点负责一部分哈希槽。当客户端写入数据时,会根据键计算出哈希值,再通过哈希值映射到对应的哈希槽,然后将数据存储到负责该哈希槽的节点上。例如,对于键
key1
,通过哈希算法得到哈希值,再根据哈希值确定其所属的哈希槽,进而找到对应的节点进行存储。 - 数据读取:客户端读取数据时,同样先根据键计算哈希值,确定所属哈希槽,然后向负责该哈希槽的节点发送读取请求。如果客户端连接的不是负责该哈希槽的节点,该节点会返回一个 MOVED 指令,告知客户端正确的节点地址,客户端再重新连接正确节点获取数据。
- Redis 是单线程的,但是为什么还那么快?
- 基于内存操作:Redis 将数据存储在内存中,内存的读写速度比磁盘快得多。与传统基于磁盘的数据库相比,不需要进行磁盘 I/O 操作,大大提高了数据的读写效率。例如,从内存中读取一个数据可能只需要几十纳秒,而从磁盘读取可能需要几毫秒甚至更长时间。
- 高效的数据结构:Redis 采用了多种高效的数据结构,如哈希表、跳跃表、压缩列表等。这些数据结构针对不同的应用场景进行了优化,能够快速地执行插入、删除、查找等操作。例如,哈希表用于实现键值对存储,查找时间复杂度接近 O (1) 。
- 事件驱动和 I/O 多路复用:Redis 使用事件驱动模型来处理客户端请求,通过 I/O 多路复用技术(如 epoll),可以同时监听多个客户端连接的 I/O 事件。当有事件发生时,才会处理对应的请求,避免了不必要的等待和资源浪费,提高了处理请求的效率。
- 能解释一下 I/O 多路复用模型?
- 基本概念:I/O 多路复用是一种同步 I/O 模型,它允许一个线程同时监听多个文件描述符(可以理解为多个网络连接或 I/O 设备)的 I/O 事件。传统的 I/O 模型中,一个连接需要一个线程来处理,当连接数增多时,线程开销会很大。而 I/O 多路复用通过一个线程,借助操作系统提供的函数(如 Linux 下的 select、poll、epoll)来监控多个连接的状态,当某个连接有数据可读或可写时,才对其进行处理。
- 工作原理:以 epoll 为例,应用程序首先创建一个 epoll 实例,然后通过 epoll_ctl 函数向这个实例中添加需要监控的文件描述符以及对应的事件(读事件或写事件)。接着,应用程序调用 epoll_wait 函数阻塞等待,当有事件发生时,epoll_wait 函数会返回发生事件的文件描述符列表,应用程序再对这些文件描述符对应的连接进行相应的 I/O 操作(如读取数据或写入数据) 。这样就实现了一个线程管理多个连接的 I/O 操作,提高了资源利用率和程序性能。