Redis는 메모리 내 데이터베이스이며 데이터는 메모리에 저장됩니다. 프로세스 종료로 인한 데이터의 영구적인 손실을 방지하려면 Redis의 데이터를 어떤 형태로든 메모리에서 저장해야 합니다. 또는 명령)을 정기적으로 하드 드라이브에 저장합니다. 다음에 Redis가 다시 시작되면 영구 파일을 사용하여 데이터 복구를 수행합니다. 또한 재해 백업 목적으로 영구 파일을 원격 위치에 복사할 수 있습니다.
Redis는 다양한 수준의 지속성 방법을 제공합니다. 하나는 RDB이고 다른 하나는 AOF입니다.
RDB 지속성은 지정된 시간 간격 내에 데이터 세트의 특정 시점 스냅샷을 생성하고 데이터베이스 스냅샷을 바이너리 형식으로 디스크에 저장할 수 있습니다.
AOF는 서버에서 실행되는 모든 변경 작업 명령을 지속적으로 기록합니다. AOF 파일의 모든 명령은 Redis 프로토콜 형식으로 저장되며 새 명령은 파일 끝에 추가됩니다. Redis는 AOF 파일의 크기가 데이터 세트 상태를 저장하는 데 필요한 실제 크기를 초과하지 않도록 백그라운드에서 AOF 파일을 다시 작성할 수도 있습니다.
Redis는 AOF 지속성과 RDB 지속성을 동시에 사용할 수 있습니다. 이 경우 Redis가 다시 시작되면 AOF 파일을 사용하여 데이터 세트를 복원하는 데 우선 순위가 부여됩니다. 왜냐하면 AOF 파일에 저장된 데이터 세트는 일반적으로 RDB 파일에 저장된 데이터 세트보다 더 완전하기 때문입니다. 서버가 실행되는 동안에만 데이터가 존재하도록 지속성을 끌 수도 있습니다.
RDB 지속성과 AOF 지속성의 유사점과 차이점을 이해하는 것이 매우 중요합니다. 다음 섹션에서는 이 두 가지 지속성 기능을 자세히 소개하고 유사점과 차이점을 설명합니다.
Redis의 첫 번째 지속성 전략인 RDB 스냅샷에 대해 이야기해 보겠습니다. Redis는 현재 메모리 데이터의 스냅샷을 데이터 파일에 저장하는 지속성 메커니즘을 지원합니다. 지속적으로 작성된 데이터베이스는 어떻게 스냅샷을 생성합니까? Redis는 fork 명령의 쓰기 시 복사 메커니즘을 교묘하게 사용하여 현재 프로세스를 하위 프로세스로 분기합니다. 하위 프로세스는 메모리 스냅샷을 기반으로 데이터를 RDB 파일에 주기적으로 유지합니다.
기본적으로 Redis는 루트 디렉터리에 dump.rdb라는 바이너리 파일로 데이터베이스 스냅샷을 저장합니다. dir 구성 매개변수를 통해 저장 디렉터리를 지정할 수 있으며, dbfilename은 파일 이름을 지정합니다. "save N M"과 같은 Redis를 설정할 수 있습니다. 즉, N초 내에 데이터 항목에 M개의 변경 사항이 있을 때 이 조건이 충족되면 데이터 세트가 자동으로 저장됩니다. 예를 들어, 10분 내에 100개의 쓰기가 있을 때 스냅샷을 생성하도록 구성하거나, 1분 내에 1,000개의 쓰기가 있을 때 스냅샷을 생성하도록 구성할 수 있으며 동시에 적용되는 여러 규칙을 지원합니다. 규칙이 일치하면 적용됩니다. 이러한 규칙의 정의는 Redis를 다시 시작하지 않고도 Redis가 실행되는 동안 Redis CONFIG SET 명령을 통해 규칙을 설정할 수도 있습니다.
예를 들어 다음 설정을 사용하면 Redis가 "60초 내에 최소 1000개의 키가 변경되었습니다"라는 조건을 충족할 때 데이터 세트를 자동으로 저장하게 됩니다.
save 60 1000
SAVE 또는 BGSAVE를 호출하여 수동으로 저장할 수도 있습니다. Redis는 데이터 세트 저장 작업을 수행합니다. SAVE 명령은 동기화 작업을 수행하고 모든 데이터의 스냅샷을 RDB 파일 형식으로 저장합니다. SAVE 명령은 모든 클라이언트 요청을 차단하므로 프로덕션 환경에서 직접 사용되는 경우는 거의 없습니다. 대신 BGSAVE 명령을 사용할 수 있습니다. BGSAVE 명령은 하위 프로세스를 포크하여 실행되므로 클라이언트 요청은 차단되지 않습니다. 하위 프로세스만 포크하면 서버가 차단됩니다. 또한 RDB 지속성을 자동으로 트리거할 때 Redis는 지속성을 위해 SAVE 대신 BGSAVE를 선택합니다.
Redis 자동 RDB 지속성은 serverCron 주기적 작업 기능, 더티 카운터 및 lastsave 타임스탬프를 통해 내부적으로 구현됩니다. ServerCron은 100ms마다 실행되어 "save N M"이 조건을 충족하는지 확인하는 것을 포함하여 서버 상태를 확인하고, 그렇다면 BGSAVE를 실행합니다. 물론 AOF 재작성 확인도 포함됩니다. 더티 카운터는 Redis 서버에서 유지 관리하는 상태로, 마지막 BGSAVE/SAVE 명령이 실행된 이후 서버 상태가 수정(추가, 삭제 및 수정 포함)된 횟수를 기록합니다. 더티는 0으로 재설정됩니다. lastsave 타임스탬프는 Redis 서버에 의해 유지되는 상태이기도 하며 BGSAVE/SAVE가 마지막으로 성공적으로 실행된 시간을 기록합니다. 현재 시간에서 lastsave를 뺀 값은 M을 충족해야 합니다.
수동 및 자동 외에도 BGSAVE를 트리거하는 몇 가지 다른 상황이 있습니다.
마스터-슬레이브 복제 시나리오에서 슬레이브 노드가 전체 복사 작업을 수행하면 마스터 노드는 BGSAVE 명령을 실행하고 rdb 파일을 슬레이브 노드에 전송합니다. shutdown 명령을 실행하면 RDB 지속성이 자동으로 수행됩니다. 또한 새로운 프로세스에서 쓰기 작업이 수행되기 때문에 새로운 RDB 파일이 생성되면 Redis에서 생성된 하위 프로세스가 먼저 데이터를 임시 파일에 쓴 다음 원자 이름 변경 시스템을 호출한다는 점을 이해해야 합니다. 언제든지 오류가 발생하더라도 Redis RDB 파일을 항상 사용할 수 있도록 임시 파일의 이름을 RDB 파일로 바꾸십시오.
这种持久化方式被称为快照(snapshot)。但是,我们可以很明显的看到,RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,如果可以忍受间隔内数据丢失,我们也推荐这些业务使用RDB的方式进行持久化,因为开启RDB的代价并不高。但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB就无能为力了,所以Redis引入了另一个重要的持久化机制,AOF日志方式持久化。
为了尽可能使RDB文件体积减小,Redis默认采用LZF算法对RDB文件进行压缩。虽然压缩耗时,但是可以大大减小RDB文件的体积,因此压缩默认开启,参数为rdbcompression。需要注意的是,RDB文件的压缩并不是针对整个文件进行的,而是对数据库中的字符串进行的,且只有在字符串达到一定长度(20字节)时才会进行。
除了压缩,你也可以检验RDB文件,通过参数rdbchecksum设置,默认为yes。在写入文件和读取文件时都起作用,关闭checksum在写入文件和启动文件时大约能带来10%的性能提升,但是数据损坏时无法发现。
另外,当bgsave出现错误时,Redis是否停止执行写命令。Redis提供了一个参数stop-writes-on-bgsave-error,设置为yes,则当硬盘出现问题时,可以及时发现,避免数据的大量丢失;设置为no,则Redis无视bgsave的错误继续执行写命令,当对Redis服务器的系统(尤其是硬盘)使用了监控时,该选项考虑设置为no。
父进程通过fork操作可以创建子进程,第一代Unix系统实现了一种傻瓜式的进程创建:当执行fork系统调用时,内核复制父进程的整个用户空间并把复制得到的那一份分配给子进程。这种行为时非常耗时的,因为它需要完成以下几项任务:为子进程的页表分配页面、为子进程的页分配页面、初始化子进程的页表、把父进程的页复制到子进程对应的页中。
现在Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候。所以就算fork很大内存的进程,对内存的消耗和耗时都很小。
现在虽然fork时,子进程不会复制父进程的数据空间,但是会复制内存页表(页表相当于内存的索引、目录);父进程的数据空间越大,内存页表越大,fork时复制耗时也会越多。这个问题也是导致Redis内存不宜过大的原因之一,当然还有导致故障恢复时间延长也是Redis内存不宜过大的原因。
通过上面的分析,我们知道RDB快照有大概率丢失最近写入、且仍未保存到快照中的那些数据。尽管对于某些程序来说,数据安全并不是最重要的考虑因素,但是对于那些追求数据安全的程序来说,快照功能就不太适用了。从1.1版本开始,Redis增加了一种实时性更好的持久化方式,即AOF持久化。AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与RDB相比,AOF的实时性更好,因此已成为主流的持久化方案。
AOF文件与MySQL数据库的binlog不同的是,AOF是一种纯文本格式,具有兼容性好、可读性强、容易处理、操作简单避免二次开销等优点,它记录的内容就是一个个的Redis标准命令。开启AOF持久化命令如下:
appendonly yes appendfilename "appendonly.aof"
从现在开始,每当Redis执行一个改变数据集的命令时(比如SET),这个命令就会被追加到AOF文件的末尾。这样的话,当Redis重新启时,程序就可以通过重新执行AOF文件中的命令来达到重建数据集的目的。
由于需要记录Redis的每条写命令,因此AOF不需要触发,下面介绍AOF的执行流程:
Redis先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。
Redis提供了多种AOF缓存区的同步文件策略,策略涉及到操作系统的write函数和fsync函数,说明如下:
파일 쓰기 효율성을 높이기 위해 최신 운영 체제에서는 사용자가 쓰기 함수를 호출하여 파일에 데이터를 쓸 때 일반적으로 운영 체제는 버퍼가 채워지거나 지정된 값을 초과하면 데이터를 메모리 버퍼에 임시로 저장합니다. 시간 제한이 있는 경우 버퍼 데이터는 실제로 하드 디스크에 기록됩니다. 이러한 작업은 효율성을 향상시키지만 보안 문제도 발생합니다. 컴퓨터가 종료되면 메모리 버퍼의 데이터가 손실되므로 시스템은 운영 체제를 강제로 작동시킬 수 있는 fsync 및 fdatasync와 같은 동기화 기능도 제공합니다. 버퍼에 있는 데이터를 즉시 전송합니다. 데이터 보안을 보장하기 위해 데이터는 하드 디스크에 기록됩니다.
AOF 캐시 영역의 동기화 파일 전략은 매개변수appendfsync에 의해 제어됩니다. 각 값의 의미는 다음과 같습니다.
always: aof_buf에 명령이 작성된 직후 시스템 fsync 작업이 호출되어 AOF 파일. fsync가 완료된 후 스레드가 반환됩니다. 이 경우 모든 쓰기 명령은 AOF 파일에 동기화되어야 하며 하드 디스크 IO는 성능 병목 현상이 발생합니다. Redis는 약 수백 개의 TPS 쓰기만 지원할 수 있으므로 SSD를 사용해도 Redis의 성능이 심각하게 저하됩니다. SSD), 초당 수만 개의 명령만 처리할 수 있어 SSD의 수명이 크게 단축됩니다.
no: 명령이 aof_buf에 작성된 후 시스템 쓰기 작업이 호출되고 AOF 파일이 fsync 동기화되지 않습니다. 동기화는 운영 체제에서 처리되며 동기화 기간은 일반적으로 30초입니다. 이 경우 파일 동기화 시간을 제어할 수 없으며, 버퍼에 많은 양의 데이터가 축적되어 데이터 보안을 보장할 수 없습니다. Everysec: 명령이 aof_buf에 기록된 후 시스템 쓰기 작업이 호출됩니다. 쓰기가 완료된 후 스레드는 전용 스레드에 의해 초당 한 번씩 호출됩니다. Everysec은 앞서 언급한 두 가지 전략, 즉 성능과 데이터 보안 간의 균형을 절충한 것이므로 Redis의 기본 구성이자 권장 구성입니다.
AOF는 파일 끝에 명령을 계속해서 추가하는 방식으로 작동하기 때문에 작성되는 명령의 수가 계속해서 늘어나면 AOF 파일의 크기도 점점 커지게 됩니다. 예를 들어, 카운터에서 INCR을 100번 호출하면 AOF 파일은 카운터의 현재 값을 저장하기 위해 100개의 항목을 사용해야 합니다. 그러나 실제로는 SET 명령 하나만 사용하면 카운터의 현재 값을 저장하는 데 충분하며 나머지 99개의 레코드는 실제로 중복됩니다. 또한 일부 만료된 데이터와 제거할 수 있는 유효하지 않은 데이터도 있습니다.
과도하게 큰 AOF 파일은 서버의 정상적인 작동에 영향을 미칠 뿐만 아니라 데이터 복구 시간도 너무 오래 걸립니다. 이러한 상황을 처리하기 위해 Redis는 서비스 클라이언트를 중단하지 않고 AOF 파일을 다시 빌드할 수 있는 흥미로운 기능을 지원합니다. BGREWRITEAOF 명령을 실행하면 Redis는 현재 데이터 세트를 재구성하는 데 필요한 최소 명령이 포함된 새 AOF 파일을 생성합니다.
AOF REWRITE(다시 쓰기) 생성 프로세스는 RDB 스냅샷과 유사하며 둘 다 쓰기 중 복사 메커니즘을 교묘하게 활용합니다. 또한 하위 프로세스를 포크합니다(현재 메인 스레드는 차단됨). 하위 프로세스는 메모리 스냅샷 및 명령 병합 규칙에 따라 새 AOF 파일에 씁니다. 기본 프로세스가 하위 스레드를 포크하고 계속해서 요청을 수락하면 모든 쓰기 명령은 여전히 AOF 버퍼(aof_buf)에 기록되고 원래 AOF 메커니즘의 정확성을 보장하기 위해appendsync 정책에 따라 하드 디스크에 동기화됩니다. 그러나 포크 작업은 쓰기 중 복사 기술을 사용하므로 자식 프로세스는 포크 작업 중에만 메모리 데이터를 공유할 수 있습니다. 상위 프로세스가 여전히 명령에 응답하고 있으므로 Redis는 AOF 재작성 버퍼(aof_rewrite_buf)를 사용하여 새 로그의 이 부분을 저장하여 새 AOF 파일 생성 중에 데이터의 이 부분이 손실되는 것을 방지합니다. 즉, bgrewriteaof 실행 중에 Redis 쓰기 명령이 aof_buf 및 aof_rewirte_buf 두 버퍼에 동시에 추가됩니다.
하위 프로세스가 새 AOF 파일 쓰기를 마치면 상위 프로세스에 신호를 보내고 상위 프로세스는 정보 지속성을 통해 볼 수 있는 통계 정보를 업데이트합니다. 그런 다음 상위 프로세스는 AOF 재작성 버퍼의 데이터를 새 AOF 파일에 기록하여 새 AOF 파일에 저장된 데이터베이스 상태가 서버의 현재 상태와 일치하는지 확인합니다. 그런 다음 원자 이름 바꾸기 명령을 호출하여 이전 AOF 파일을 새 AOF 파일로 대체하여 AOF 재작성을 완료합니다.
메인 프로세스가 aof_rewrite_buf 캐시를 새 로그 파일에 추가하므로 여기서 주의해야 합니다. 기본 프로세스가 로그를 추가하면 다른 요청을 처리하지 않습니다. aof_rewrite_buf가 수백 M과 같이 특히 큰 경우 Redis가 몇 초 또는 수십 초 동안 응답하지 않을 수 있습니다.
위 프로세스에서 RDB 및 AOF 작업은 모두 순차 IO 작업이며 성능이 매우 높다는 것을 알 수 있습니다. RDB 파일이나 AOF 로그를 통해 데이터베이스를 복원할 때도 해당 데이터를 순차적으로 읽어 메모리에 로드한다. 따라서 디스크를 임의로 읽는 일이 발생하지 않습니다.
파일 재작성 트리거는 수동 트리거와 자동 트리거로 나뉩니다.
수동 트리거: bgrewriteaof 명령을 직접 호출합니다. 이 명령의 실행은 bgsave와 다소 유사합니다. 두 포크 하위 프로세스는 모두 특정 작업만 수행합니다. 포크 시간 차단 후에 수행됩니다.
자동 트리거링: auto-aof-rewrite-min-size 및 auto-aof-rewrite-percentage 매개변수와 aof_current_size 및 aof_base_size 상태를 기반으로 트리거 시간을 결정합니다.
auto-aof-rewrite-min-size는 AOF 다시 쓰기를 수행할 때 파일의 최소 크기를 나타냅니다. 기본값은 64MB입니다.
auto-aof-rewrite-percentage表示执行AOF重写时,当前AOF大小(即aof_current_size)和上一次重写时AOF大小(aof_base_size)的比值,即增长比例达到设定值。
只有当auto-aof-rewrite-min-size和auto-aof-rewrite-percentage两个参数同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。
其中,参数可以通过config get命令查看:
127.0.0.1:6391> CONFIG GET auto-aof-rewrite-min-size 1) "auto-aof-rewrite-min-size"2) "64000000"127.0.0.1:6391> CONFIG GET auto-aof-rewrite-percentage 1) "auto-aof-rewrite-percentage"2) "100"
状态可以通过info persistence查看:
127.0.0.1:6379> info persistence# Persistenceaof_enabled:1 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:0 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_current_size:40876638 aof_base_size:2217565 aof_pending_rewrite:0 aof_buffer_length:0 aof_rewrite_buffer_length:0 aof_pending_bio_fsync:0 aof_delayed_fsync:0
另外在aof rewrite过程中,是否采取增量”文件同步”策略,由参数aof-rewrite-incremental-fsync控制,默认为”yes”,而且必须为yes。rewrite过程中,每32M数据进行一次文件同步,这样可以减少”aof大文件”写入对磁盘的操作次数。
bgrewriteaof机制,在一个子进程中进行aof的重写,从而不阻塞主进程对其余命令的处理,同时解决了aof文件过大问题。现在问题出现了,同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,现在no-appendfsync-on-rewrite参数出场了。
如果该参数设置为no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题。如果设置为yes呢?这就相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候Redis挂掉,就会丢失数据。丢失多少数据呢?在Linux的操作系统的默认设置下,最多会丢失30s的数据。因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。
前面提到过,在AOF中,如果AOF缓冲区的文件同步策略为everysec,则:在主线程中,命令写入aof_buf后调用系统write操作,write完成后主线程返回;fsync同步文件操作由专门的文件同步线程每秒调用一次。这种做法的问题在于,如果硬盘负载过高,那么fsync操作可能会超过1s;如果Redis主线程持续高速向aof_buf写入命令,硬盘的负载可能会越来越大,IO资源消耗更快;如果此时Redis进程异常退出,丢失的数据也会越来越多,可能远超过1s。
为此,Redis的处理策略是这样的:主线程每次进行AOF会对比上次fsync成功的时间;如果距上次不到2s(也就是延迟了1s),主线程直接返回;如果超过2s,则主线程阻塞直到上一次fsync同步完成。因此,如果系统硬盘负载过大导致fsync速度太慢,会导致Redis主线程的阻塞;此外,使用everysec配置,AOF最多可能丢失2s的数据,而不是1s。具体看Redis AOF刷新策略分析
AOF追加阻塞问题定位的方法,监控info Persistence中的aof_delayed_fsync,当AOF追加阻塞发生时(即主线程等待fsync而阻塞),该指标累加。另外,AOF阻塞时的Redis日志:Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
如果AOF追加阻塞频繁发生,说明系统的硬盘负载太大;可以考虑更换IO速度更快的硬盘,或者通过IO监控分析工具对系统的IO负载进行分析。
对于pipelining的操作,其具体过程是客户端一次性发送N个命令,然后等待这N个命令的返回结果被一起返回。通过采用pipilining就意味着放弃了对每一个命令的返回值确认。由于在这种情况下,N个命令是在同一个执行过程中执行的。所以当设置appendfsync为everysec时,可能会有一些偏差,因为这N个命令可能执行时间超过1秒甚至2秒。但是可以保证的是,最长时间不会超过这N个命令的执行时间和。
服务器可能在程序正在对AOF文件进行写入时停机,如果停机造成了 AOF 文件出错(corrupt),那么Redis在重启时会拒绝载入这个AOF文件, 从而确保数据的一致性不会被破坏。当发生这种情况时,可以用以下方法来修复出错的 AOF 文件:为现有的AOF文件创建一个备份。然后使用Redis附带的redis-check-aof –fix程序对原来的AOF文件进行修复。
然后可选使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。再次重启Redis服务器,等待服务器载入修复后的AOF文件,并进行数据恢复。
그러나 AOF 파일의 끝이 불완전하고(갑작스러운 시스템 가동 중단으로 인해 파일 끝이 불완전해질 수 있음) aof-load-truncated 매개변수가 켜져 있으면 로그에 경고가 출력되며, Redis는 AOF 파일의 끝을 무시하고 성공적으로 시작됩니다. aof-load-truncated 매개변수는 기본적으로 활성화됩니다.
RDB는 크기가 작고 네트워크 전송 속도가 빠른 매우 컴팩트한 파일로 특정 시점에 설정된 Redis 데이터를 저장합니다. 이러한 종류의 파일은 백업에 매우 적합하며 복구 속도가 AOF보다 훨씬 빠릅니다. 물론, RDB의 가장 중요한 장점 중 하나는 AOF에 비해 성능에 미치는 영향이 상대적으로 적다는 것입니다. RDB 파일을 저장할 때 상위 프로세스가 수행해야 하는 유일한 작업은 하위 프로세스를 분기하는 것입니다. 그러면 하위 프로세스가 모든 후속 저장 작업을 처리합니다. 상위 프로세스는 디스크 I/O 작업을 수행할 필요가 없습니다.
RDB 파일의 치명적인 단점은 데이터 스냅샷의 지속성 방식에 따라 실시간 지속성을 달성할 수 없다는 것입니다. 오늘날 데이터가 점점 더 중요해지면 대량의 데이터 손실이 허용되지 않는 경우가 많기 때문에 AOF 지속성은 주류가 되다. 또한 RDB 파일은 특정 형식을 충족해야 하며 호환성이 좋지 않아야 합니다(예: 이전 버전의 Redis는 새 버전의 RDB 파일과 호환되지 않습니다).
RDB 지속성에 대응하여 AOF의 장점은 2단계 지속성을 지원하고 호환성이 좋다는 점입니다. fsync 없음, 매초 fsync, 쓰기 명령이 실행될 때마다 fsync 등 다양한 fsync 정책을 설정할 수 있습니다. AOF의 기본 정책은 초당 한 번 fsync입니다. 이 구성에서 Redis는 여전히 좋은 성능을 유지할 수 있으며, 오류가 발생하더라도 최대 1초의 데이터만 손실됩니다. AOF 파일은 추가 작업만 수행하는 로그 파일(append only log)이므로 로그에 어떤 이유로 인해 불완전한 명령이 포함되어 있어도(예: 쓰기 디스크가 꽉 찼습니다. 쓰기 도중 중지됨) redis-check-aof 도구를 사용하면 이 문제를 쉽게 해결할 수도 있습니다.
Redis는 AOF 파일 크기가 너무 커지면 백그라운드에서 자동으로 AOF를 다시 작성할 수 있습니다. 다시 작성된 새 AOF 파일에는 현재 데이터 세트를 복원하는 데 필요한 최소 명령 세트가 포함되어 있습니다. Redis는 새 AOF 파일을 생성하는 과정에서 계속해서 기존 AOF 파일에 명령을 추가하므로 전체 재작성 작업은 절대적으로 안전합니다. 재작성 프로세스 중에 종료가 발생하더라도 기존 AOF 파일은 손실되지 않습니다. . 새 AOF 파일이 생성되면 Redis는 이전 AOF 파일에서 새 AOF 파일로 전환하고 새 AOF 파일에 추가하기 시작합니다. AOF 파일은 데이터베이스에서 수행되는 모든 쓰기 작업을 순서대로 저장하므로 이러한 쓰기 작업은 Redis 프로토콜 형식으로 저장되므로 AOF 파일의 내용은 매우 읽기 쉽고 파일을 분석하기 쉽습니다. 구문 분석). AOF 파일 내보내기(내보내기)도 매우 간단합니다. 예를 들어 실수로 FLUSHALL 명령을 실행했지만 AOF 파일을 덮어쓰지 않은 경우 서버를 중지하고 AOF 끝에서 FLUSHALL 명령을 제거합니다. 파일을 저장하고 Redis를 다시 시작하면 FLUSHALL이 실행되기 전의 상태로 데이터 세트를 복원할 수 있습니다.
AOF 파일은 일반적으로 RDB 파일보다 크기가 크고 복구 속도도 느립니다. 동일한 데이터 세트의 경우 사용된 fsync 전략에 따라 AOF가 RDB보다 느릴 수 있습니다. 일반적인 상황에서 초당 fsync 성능은 여전히 매우 높으며, fsync를 끄면 AOF가 RDB만큼 빨라질 수 있습니다. 또한, AOF에는 과거에 특정 명령으로 인해 AOF 파일을 다시 로드할 때 데이터 세트를 저장했을 때의 원래 상태로 복원할 수 없는 버그가 있었습니다. AOF 파일에서는 이런 종류의 버그가 흔하지 않지만, RDB에서는 이런 종류의 버그가 발생하는 것이 거의 불가능합니다.
우선, RDB이든 AOF이든 지속성을 켜면 성능 비용이 발생한다는 점을 이해해야 합니다. RDB 지속성의 경우 한편으로는 bgsave가 포크 작업을 수행할 때 Redis 기본 프로세스가 차단되고, 반면, 하위 프로세스가 하드 디스크에 데이터를 쓰는 경우에도 IO 부담이 발생합니다. 그러나 기업이 몇 분에서 10분 정도의 데이터 손실을 허용할 수 있다면(그리고 대기 데이터베이스를 사용하지 않는 경우) RDB가 좋은 선택입니다. 그렇지 않으면 AOF를 선택하세요.
AOF 지속성의 경우 하드 디스크에 데이터를 쓰는 빈도가 크게 증가하고(everysec 정책에서 두 번째 수준) IO 압력이 더 높으며 심지어 AOF 추가 차단 문제가 발생할 수도 있습니다(이 차단에 대해서는 나중에 자세히 설명합니다) 또한 AOF 파일 재작성은 RDB의 bgsave와 유사하며 하위 프로세스에 대한 포크 및 IO 압력 중 차단 문제가 있습니다. 상대적으로 말하면 AOF는 하드 디스크에 데이터를 더 자주 쓰기 때문에 Redis 기본 프로세스의 성능에 더 큰 영향을 미칩니다.
在实际生产环境中,根据数据量、应用对数据的安全要求、预算限制等不同情况,会有各种各样的持久化策略;如完全不使用任何持久化、使用RDB或AOF的一种,或同时开启RDB和AOF持久化等。此外,持久化的选择必须与Redis的主从策略一起考虑,因为主从复制与持久化同样具有数据备份的功能,而且主机master和从机slave可以独立的选择持久化方案。比如完全关闭master持久化(包括RDB和AOF),这样可以让master的性能达到最好;而slave可以只开启AOF。但这种情况下,如果master服务因为故障宕掉了,如果系统中有自动拉起机制(即检测到服务停止后重启该服务)将master自动重启,由于没有持久化文件,那么master重启后数据是空的,slave同步数据也变成了空的,意味着数据丢失。所以尽量避免这种情况出现。
在版本号大于等于2.4的Redis中,BGSAVE执行的过程中,不可以执行BGREWRITEAOF。反过来说,在BGREWRITEAOF执行的过程中,也不可以执行BGSAVE。这可以防止两个Redis后台进程同时对磁盘进行大量的I/O操作。
如果BGSAVE正在执行,并且用户显示地调用BGREWRITEAOF命令,那么服务器将向用户回复一个OK状态,并告知用户,BGREWRITEAOF已经被预定执行: 一旦BGSAVE执行完毕,BGREWRITEAOF就会正式开始。当Redis启动时,如果RDB持久化和AOF持久化都被打开了,那么程序会优先使用AOF文件来恢复数据集,因为AOF文件所保存的数据通常是最完整的。
这些持久化的数据有什么用,当然是用于重启后的数据恢复。Redis是一个内存数据库,无论是RDB还是AOF,都只是其保证数据恢复的措施。所以Redis在利用RDB或AOF进行恢复的时候,会读取RDB或AOF文件,重新加载到内存中。相对于MySQL等数据库的启动时间来说,会长很多,因为MySQL本来是不需要将数据加载到内存中的。
但是相对来说,MySQL启动后提供服务时,其被访问的热数据也会慢慢加载到内存中,通常我们称之为预热,而在预热完成前,其性能都不会太高。而Redis的好处是一次性将数据加载到内存中,一次性预热。这样只要Redis启动完成,那么其提供服务的速度都是非常快的。
而在利用RDB和利用AOF启动上,其启动时间有一些差别。RDB的启动时间会更短,原因有两个,一是RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。另一个原因是RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作。在CPU消耗上要远小于AOF日志的加载。
注意:当redis启动时,如果rdb持久化和aof持久化都打开了,那么程序会优先使用aof方式来恢复数据集,因为aof方式所保存的数据通常是最完整的。如果aof文件丢失了,则启动之后数据库内容为空。
注意:如果想把正在运行的redis数据库,从RDB切换到AOF,建议先使用动态切换方式,再修改配置文件,重启数据库。(不能直接修改配置文件,重启数据库,否则数据库中数据就为空了。) 在Redis 2.2或以上版本,可以在不重启的情况下,从RDB切换到AOF :
为最新的dump.rdb文件创建一个备份,将备份放到一个安全的地方。执行以下两条命令:
127.0.0.1:6379> CONFIG SET dir /apps/redis/data/redis-8836 127.0.0.1:6379> CONFIG SET appendonly yes 127.0.0.1:6379> CONFIG SET save ""
确保命令执行之后,数据库的键的数量没有改变。确保写命令会被正确地追加到 AOF 文件的末尾。
步骤2是开启了AOF功能,Redis会阻塞直到初始AOF文件创建完成为止,之后Redis会继续处理命令请求,并开始将写入命令追加到AOF文件末尾。
步骤3用于关闭RDB功能,这一步是可选的,如果你愿意的话,也可以同时使用RDB和AOF这两种持久化功能。
위 내용은 Redis의 RDB 및 AOF 방법을 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!