电话

028-126520321

BOB半岛平台:在前一篇文章中,我们了解了Redis的基本类型及其应用场景。那么,你知道为什么Redis如此快吗?

标签: 2024-06-27 

Redis 发生故障该怎么处理?\nRedis 可以采用哪些持久化方式呢?作为云服务提供商,你会如何对你的云端版本的 Redis 进行优化呢?这篇文章将对Redis的相关原理进行分析。

的IO模型

是单线程的,除了Redis之外,Node.js也是单线程,Nginx也是单线程,但它们都展现了服务器高性能的典范。Redis 单线程的速度如此之快,这要归功于其采用了非阻塞IO和多路复用器。非阻塞I/O操作能够读取多少数据取决于内核为套接字分配的读缓冲区中的数据量。内核为套接字分配的写缓存区空闲空间的字节数决定了可以写入多少字节。事件轮询(多路复用)

非阻塞输入输出存在一个问题,即当线程开始读取数据时,可能会读取部分数据后就返回了,线程需要知道什么时候才能继续读取。当数据到达时,线程是如何获得通知的。当缓冲区被填满,写操作无法完成时,剩余的数据应该在何时继续写入,同时线程也应该得到通知。

是一个非常简洁的事件轮询API,如图所示。选择功能是由操作系统提供的。当存在大量描述符时,性能会显著下降。当代操作系统使用多路复用技术的实现方式有:epoll(Linux)和kqueue(FreeBSD和macOS)。目前支持多路I/O复用的系统调用有select,pselect,poll,epoll。多路I/O复用是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但是,select、pselect、poll和epoll在本质上都属于同步I/O,因为它们在读写事件准备就绪后需要自己负责进行读写操作。换句话说,这个读写过程是阻塞的。而异步I/O不需要自己负责读写操作,它的实现会将数据从内核拷贝到用户空间。

select和epoll的不同之处

select

在于平台的兼容性,select本质上是通过设置或检查存储fd标志位的数据结构来执行下一步处理。

select最大的不足是单个进程打开的FD数量受到限制,它由FD_SETSIZE设置,默认值为1024

在扫描套接字时,使用的是线性扫描-基于轮询的方法,效率较低。epoll是2.6内核引入的一种新机制,它是对select和poll的增强版本。epoll利用一个文件描述符管理多个描述符,并将用户关心的文件描述符事件存储到内核的一个事件表中,这样可以减少用户空间和内核空间之间的数据拷贝次数。它的原理实际上是基于 epoll,支持水平触发和边缘触发。最大的特点在于边缘触发,它只告诉进程哪些文件描述符刚刚变为就绪状态,并且只会通知一次。epoll还有一个重要特点,它使用"事件"的就绪通知方式。当使用epoll_ctl注册fd后,一旦该fd就绪,内核会使用类似callback的回调机制来激活该fd,然后epoll_wait就可以收到通知。

它的优点有以下几个:

1、没有最大并发连接的限制,可以打开的文件描述符(FD)的上限远大于1024(在1G的内存上可以监听约10万个端口)。2、提高效率的方式不是轮询,随着FD数目的增加效率不会下降。利用 mmap() 文件映射内存来加速 内存拷贝和消息在内核空间之间的传递,进而减少 epoll 中的复制开销。单线程是如何处理相应请求的?通过指令队列、响应队列和定时任务的设计来处理请求。指令队列是用来排队并处理客户端指令的,采用先到先服务的策略来响应队列里的请求。只有在队列中有数据时,才会将客户端fd添加到队列中,以避免浪费CPU资源。除了响应IO事件外,服务器还需要处理其他任务,如定时任务。例如,定时任务是非常重要的事情。当线程在select系统调用上被阻塞时,定时任务就无法按时调度了。Redis是如何解决这个问题的呢?Redis会把定时任务记录在一个最小堆的数据结构里。在这个堆中,最立即要执行的任务会排在堆的顶部。Redis 在每个循环周期都会立即处理最小堆里已经到期的任务。处理完成后,需要记录执行最快的任务所需的时间,这个时间就是select系统调用的timeout参数。由于 Redis 能够知道在未来的超时时间内,没有其他的定时任务需要处理,因此可以放心地睡眠超时时间。Nginx、Node以及Redis在事件处理方面的原理相似。Redis 的请求在本质上与一次rpc 的调用相似。在rpc中,通信协议的设计是非常重要的。Redis 的创作者认为,数据库系统通常遇到的瓶颈不是在于网络流量,而是在于数据库内部逻辑处理能力。因此,尽管Redis使用了浪费流量的文本协议,它仍然能够实现极高的访问性能。Redis是一种将所有数据存储在内存中,使用单线程提供服务的数据存储系统。当单个节点占用一个CPU核心时,它可以实现非常高的QPS,高达10万次/秒。RESP(Redis 序列化协议)是 Redis 的一种序列化协议。它是一种直观易懂的文本协议,主要优势在于实现过程简单,解析性能极佳。Redis协议包含很多冗余的换行符,但这并不妨碍它成为互联网技术领域备受欢迎的一种文本协议。有许多开源项目采用 RESP 作为它们的通信协议。在技术领域,性能并非万能,还需要考虑简单易懂和易实现等方面,需要进行合理平衡。一款优秀的中间件都会考虑持久化方面的问题。Redis的数据全部存储在内存中,一旦发生故障,数据就会全部丢失,因此需要有一种机制来确保Redis的数据不会因故障而丢失。这种机制就是Redis的持久化机制。Redis的持久化机制主要包括两种,一种是快照(RDB,Redis DataBase),另一种是日志(AOF,Append Only File)。RDB持久化原理: Redis利用操作系统的多进程(cow写时复制)机制来实现快照持久化;手动使用save、bgsave命令;通过配置文件进行设置。子进程通过fork调用glibc函数产生,负责处理快照持久化。子进程一开始会与父进程共享代码段和数据段,随着父进程的修改,共享页面逐渐分离,创建进程速度加快;内存增长不会超过原来的2倍。同时,在另一个Redis实例中,由于冷数据比例较高,因此很少会出现所有页面都被分离的情况。通常情况下,分离的是其中的某些页面。Redis 实例通常包含成千上万大小为 4K 的页面子进程。这些数据并没有发生变化,因此我们可以毫无顾虑地遍历这些数据,并序列化地写入磁盘。Redis 实例中,每个页面通常都只有 4K 的大小。在页面子进程的数据没有发生变化时,可以无虑遍历数据并对其进行序列化写入磁盘。AOF 日志存储的是 Redis 服务器执行的指令顺序序列,仅会记录对内存进行修改的指令操作。在 Redis 实例中,通常会有成千上万条的页面子进程数据没有发生变化。随着操作的推进,指令文本的规模逐渐增大。需要重新撰写AOF,日志进行精简,Redis 提供bgrewriteaof命令以对AOF进行精简。其原理是创建一个子进程来遍历内存,对内存进行序列化,并生成一个新的AOF文件,包括此期间的增量。Linux 的 glibc 提供了 fsync(int fd) 函数,该函数用于将内核缓存中的数据强制刷入磁盘。由于 fsync 的执行速度较慢,在生产环境中通常会每隔一秒执行一次,且支持进行配置。Redis在执行指令之前会先写日志,而leveldb和HBase则相反。关于redis的运维经验,不应该在主节点进行持久化操作,而应该在从节点进行持久化,因为持久化是一个非常耗时的IO操作。为什么需要进行混合持久化?混合持久化的好处是什么?首先,进行fork操作时需要复制页表。在大内存下,这会阻塞服务器,并导致延迟在百毫秒或秒级别的急剧增加。因此,这个操作比较适合于每天定时进行全备份的场景。一些云服务提供商的解决方案,例如使用redis结合rocksDB。我们将从几个方面来进行分析。将增量数据写入Redis内存,并记录增加计数。后台线程异步将增量数据应用到RocksDB中。确保数据可靠性,RocksDB包含全量数据,彻底避免Fork调用。在启动时,从RocksDB加载全量索引信息到内存。对于数据读取,直接从Redis内存中读取。如果数据不在Redis内存中,则先整体加载到Redis再读取。对于简单命令,可以直接从RocksDB中读取。RocksDB是一种可嵌入、持久的键值存储系统。该项目最初由Facebook发起,旨在开发一款数据库软件,能够与快速存储设备(尤其是闪存)性能相匹敌,以满足高负载服务的需求。这个库是用于存储键和值的,可以存储任意大小的字节流,是一个C++库。它能够执行原子级的读取和写入操作。RocksDB的配置功能非常灵活,可以根据需求对其进行配置,以适应不同的生产环境,包括纯内存、Flash、硬盘或HDFS。它兼容多种压缩算法,并提供了方便的生产环境维护和调试工具。

数据结构编码

是为每个key编码一个RocksDB metakey,用于存储key的元数据。所有的元数据键都是相邻存储的,因此启动加载效率很高。 对于复杂键中的每个元素,在RocksDB中都会对应一个数据键,这些元素也是相邻存储在RocksDB中的,所以访问效率也很高。简化String类型,将metakey和Datakey合并以优化IO。{内存数据换出:后台定期检查内存使用是否超过阀值,根据访问频率和大小等条件选择要淘汰的键。}当某个key被频繁读取或有大量读取操作(o(n)),需要将该key的磁盘数据换入RocksDB,以加速访问。当key被写入时,数据将被整体换入内存。默认情况下,磁盘数据的换入是通过后台多线程异步进行的。使用RocksDB checkoutpoint来进行主备同步和迁移的全量同步,以替代RDB,避免使用fork系统调用。备份接收到checkoutpoint数据后,只需加载元数据键就可以实现增量同步。增量同步则是从checkoutpoint对应的aof binlog位点开始进行,当增量同步断开时,可以直接从断开的位置继续同步,而无需触发全量同步。一些额外的技术知识是有关管道的本质:客户端提供指令,并且管道中包含多条指令;客户端改变管道中指令列表的读写顺序,可以大幅度减少IO时间。Redis自带压力测试工具——redis-beanchmark。普通的设定是,当小对象压缩并且Redis的内存使用不超过4G时,使用32位编译。

{z}

BOB半岛官方

BOB半岛平台

在前一篇文章中,我们了解了Redis的基本类型及其应用场景。那么,你知道为什么Redis如此快吗?

在前一篇文章中,我们了解了Redis的基本类型及其应用场景。那么,你知道为什么Redis如此快吗?

在前一篇文章中,我们了解了Redis的基本类型及其应用场景。那么,你知道为什么Redis如此快吗?

BOB半岛入口


BOB半岛老版本 BOB半岛APP

推荐新闻