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

Redis原理简述及发布订阅消息队列

目录

1 什么是Redis

2 Redis 非阻塞IO内部原理

2.1 IO多路复用策略

2.2 Reactor设计模式

3 基于PubSub的消息队列(发布-订阅)

由于集群之后存在多台服务器,并且不同客户端连接的可能是不同的服务器,因此在聊天过程中涉及到服务器之间的通信

如果单纯的将各服务器之间建立TCP连接进行通信,相当于在服务器网络之间进行广播,会造成各服务器之间耦合度太高、业务实现复杂、应对故障能力差,不利于系统扩展,并且会占用系统大量的socket资源,各服务器之间的带宽压力太大,不能够节省资源给更多的客户端提供服务。

集群部署的服务器之间进行通信,最好的方式就是引入中间件消息队列,解耦各个服务器,使得整个系统松耦合,提高服务器的响应能力,节省服务器的带宽资源:

在集群分布式环境下,常用的中间件消息队列有ActiveMQ、RabbitMQ、Kafka等,redis属于比较轻量级的中间件。

1 什么是Redis

全称是Remote Dictionary Server(远程字典服务器),是一个开源的高性能键值对(key-value)存储系统。Redis具有以下特点来支持其高并发、分布式高性能的特性:

  1. 数据库保存在内存中:仅使用磁盘进行持久化,具有快速读写的高性能,数据存储在内存中,类似于HashMap,使得数据的查找和操作时间复杂度为O(1)。Redis支持将数据持久化到硬盘上,以防止数据丢失。它提供了两种持久化方式:RDB(Redis Database)和AOF(Append Only File)。RDB是将数据定期保存到磁盘文件中,而AOF则是将每个写操作追加到文件的末尾。
  2. 基于字典结构存储:Redis的底层存储结构主要依赖于字典,也称为散列表(hash)。字典是一种键值对的存储结构,用于在内存中快速查找和访问数据。整个Redis数据库就是通过字典来存储数据的,每个键值对都被存储在字典中。因此,在对Redis进行CURD操作时,实际上是对字典中的数据进行操作。
  3. 支持多种数据结构:不仅仅支持简单的key-value类型的数据,还提供了list、set、zset和hash等更复杂的数据结构的存储。
  4. 支持数据备份:可以通过master-slave模式进行数据备份,增加了数据的可靠性和安全性。
  5. 单线程模型:它在任何给定的时间只处理一条命令,这样可以避免了多线程之间的线程同步和竞争条件问题。但是,可以通过异步I/O和事件驱动模型来提高并发读写的能力,从而实现了高性能的读写操作。
  6. 非阻塞IO:Redis使用多路复用IO模型来处理IO操作,实现了非阻塞IO。它通过监听多个socket,一次性接受多个客户端请求,并将请求放入队列中。当完整的命令到达服务端后,再去处理请求,不需要等待客户端的传输。这种方式可以提高Redis的并发处理能力。

基于以上特性,Redis在多种应用场景使用:

  1. 发布订阅系统:Redis提供了发布订阅(Pub/Sub)机制,可以用于实现消息队列、实时聊天等功能。通过订阅感兴趣的频道,客户端可以接收到相应的消息。
  2. 地图信息分析:Redis提供了地理位置相关的数据结构和命令,可以用于存储和查询地理位置信息。这使得它在地图信息分析方面具有很大的优势。
  3. 计时器和计数器:Redis提供了丰富的命令,可以用于实现计时器和计数器功能,比如记录用户的浏览量、点赞次数等。
  4. 分布式锁:Redis的setnx命令可以用于实现分布式锁。在分布式应用中,为了保证同一时刻只有一个线程执行关键代码,可以使用Redis的分布式锁功能来实现。
  5. 实时数据分析:由于Redis具有高性能和低延迟的特点,适合用于实时数据分析。可以将实时产生的数据存储在Redis中,并通过Redis提供的相关命令进行实时的数据查询和统计分析。

2 Redis 非阻塞IO内部原理

Redis内部实现采用epoll+Reactor 设计模式。 epoll中的读、写、关闭、连接都转化成了事件,利用epoll的多路复用特性结合事件驱动提高网络性能。

Redis的实现模式类似于muduo库,都是使用epoll+Reactor。因为 Redis 需要在多个平台上运行,同时为了最大化执行的效率与性能,所以会根据编译平台的不同选择不同的 I/O 多路复用函数作为子模块,提供给上层统一的接口。

2.1 IO多路复用策略

redis的多路复用, 提供了select, epoll, evport, kqueue几种选择,在编译的时候来选择一种。

select是POSIX提供的, 一般的操作系统都有支撑;
epoll 是LINUX系统内核提供支持的;
evport是Solaris系统内核提供支持的;
kqueue是Mac 系统提供支持的;

为了将所有 IO 复用统一,Redis 为所有 IO 复用统一了类型名 aeApiState,对于 epoll 而言,类型成员就是调用 epoll_wait所需要的参数
接下来就是一些对epoll接口的封装了:

包括创建 epoll(epoll_create)

注册事件(epoll_ctl)

删除事件(epoll_ctl)

阻塞监听(epoll_wait)等

创建 epoll 就是简单的为 aeApiState 申请内存空间,然后将返回的指针保存在事件驱动循环中,注册事件和删除事件就是对 epoll_ctl 的封装,根据操作不同选择不同的参数,阻塞监听是对 epoll_wait 的封装,在返回后将激活的事件保存在事件驱动中。

2.2 Reactor设计模式

Redis 服务采用 Reactor 的方式来实现文件事件处理器(每一个网络连接其实都对应一个文件描述符)

当 main 函数初始化工作完成后,就需要进行事件驱动循环,而在循环中,会调用 IO 复用函数进行监听在初始化完成后,main 函数调用了 aeMain 函数,传入的参数就是服务器的事件驱动

Redis 对于时间事件是采用链表的形式记录的,这导致每次寻找最早超时的那个事件都需要遍历整个链表,容易造成性能瓶颈。而 libevent 是采用最小堆记录时间事件,寻找最早超时事件只需要 O(1) 的复杂度。

通过Reactor的方式,可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理。

用户线程注册事件处理器之后可以继续执行做其他的工作(异步),而Reactor线程负责调用内核的select/epoll函数检查socket状态。当有socket被激活时,则通知相应的用户线程(或执行用户线程的回调函数),执行handle_event进行数据读取、处理的工作。由于select/epoll函数是阻塞的,因此多路IO复用模型也被称为异步阻塞IO模型。注意,这里的所说的阻塞是指select函数执行时线程被阻塞,而不是指socket。一般在使用IO多路复用模型时,socket都是设置为NONBLOCK的,不过这并不会产生影响,因为用户发起IO请求时,数据已经到达了,用户线程一定不会被阻塞。

3 基于PubSub的消息队列(发布-订阅)

发布订阅模式是一种消息传递模式,其中发布者发送消息而不直接指定接收者,订阅者通过注册感兴趣的主题来接收消息。当发布者发布某个主题的消息时,所有订阅该主题的消费者都会收到该消息。这种模式有效地实现了解耦,使得生产者和消费者之间的交互更加灵活,常用于事件驱动架构和消息队列系统中。

发布/订阅模式可以 1:N 的消息发布/订阅。发布者将消息发布到指定的频道频道(channel),订阅相应频道的客户端都能收到消息。

PubSub(发布订阅)是Redis2.0版本引入的消息传递模型。

优缺点:

优点
实时性:Pub/Sub 模式允许消息的即时传递,订阅者能够快速接收到发布者发送的消息,适合需要快速响应的应用场景,如实时聊天、在线游戏等。
解耦合:发布者和订阅者之间是松耦合的,发布者无需知道订阅者的存在,增强了系统的灵活性和可扩展性。
多频道支持:可以同时订阅多个频道,允许订阅者接收来自不同频道的消息。

缺点

消息丢失:如果在发布消息时没有任何订阅者在线,消息将被丢弃,无法持久化。这意味着在网络故障或 Redis 宕机时,消息会丢失。
缺乏确认机制:Pub/Sub 模式没有消息确认机制,无法保证消息是否被成功接收和处理。这可能导致消费者在处理消息时出现问题而无法重试。
性能压力:当订阅者数量较多时,发布大量消息可能会对 Redis 服务器造成较大负担,影响系统性能。

常用命令:

命令

用法

描述

SUBSCRIBE

SUBSCRIBE channel1 [channel2 ...]

订阅一个或多个频道,以接收该频道的消息。

UNSUBSCRIBE

UNSUBSCRIBE [channel1 ...]

取消对一个或多个频道的订阅。

PUBLISH

PUBLISH channel message

向指定的频道发布消息。

PSUBSCRIBE

PSUBSCRIBE pattern1* [pattern2 ...]

订阅符合特定模式的频道(支持通配符,如 *

)。

PUNSUBSCRIBE

PUNSUBSCRIBE [pattern1 ...]

取消对符合特定模式的频道的订阅。

PUBSUB

PUBSUB CHANNELS

查看当前订阅的活跃频道。

PUBSUB NUMSUB channel1 [channel2 ...]

返回指定频道的订阅者数量。

PUBSUB NUMPAT

返回当前通过模式订阅(PSUBSCRIBE)的数量。

说明:

支持通配符的命令:PSUBSCRIBEPUNSUBSCRIBE 使用通配符(如 news.*)匹配频道名。

PUBSUB 子命令:

CHANNELS:列出当前活跃的频道。

NUMSUB:查询指定频道的订阅者数量。

NUMPAT:统计模式订阅的数量。

注意:UNSUBSCRIBEPUNSUBSCRIBE 若不指定参数,默认取消所有订阅。


http://www.kler.cn/a/550202.html

相关文章:

  • 技术速递|Copilot Edits(预览版)介绍
  • ubuntu桌面东西没了,右键只有更换壁纸,显示设置和设置
  • Android 14输入系统架构分析:图解源码从驱动层到应用层的完整传递链路
  • 笔记9——循环语句:for语句、while语句
  • 通过TDE工业通讯网关解决设备通讯问题
  • 在自有ARM系统上离线安装MongoDB的坎坷历程与解决方案
  • 5.【线性代数】—— 转置,置换和向量空间
  • OpenCV(1):简介、安装、入门案例、基础模块
  • 使用 Spring Boot 和 Canal 实现 MySQL 数据库同步
  • 二、从0开始卷出一个新项目之瑞萨RZT2M双核架构通信和工程构建
  • 【实战项目】BP神经网络识别人脸朝向----MATLAB实现
  • 【蓝桥杯集训·每日一题2025】 AcWing 6122. 农夫约翰的奶酪块 python
  • 如何将模型长度扩展到100万:Llama 3的NTK-aware插值技术解析 小学生都懂的
  • React进阶之React核心源码解析(二)
  • Zabbix——监控Windows下某个文件夹的所有文件变化
  • JUC并发-wait和notify以及Atomic原理
  • 开源模型应用落地-LangGraph101-探索 LangGraph 短期记忆
  • 5.日常英语笔记
  • 鸿蒙5.0实战案例:数据库版本升级案例
  • Tomcat如何处理Http请求