redis源代码分析18–持久化之aof
Redis的aof功能的目的是在性能和持久化粒度上对持久化机制提供更好的支持。 快照方式持久化的粒度有时间(秒)和改变的key数两种,如果持久化的粒度较小,对性能会有较大的影响,因为每次都是dump整个db;如果持久化的粒度较大,则在指定时间内指定数目的数
Redis的aof功能的目的是在性能和持久化粒度上对持久化机制提供更好的支持。
快照方式持久化的粒度有时间(秒)和改变的key数两种,如果持久化的粒度较小,对性能会有较大的影响,因为每次都是dump整个db;如果持久化的粒度较大,则在指定时间内指定数目的数据的持久化无法保证。而aof持久化的粒度是每次会修改db数据的命令,因此粒度是最小的了,跟日志方式有点类似,由于仅记录一条命令,性能也最好。另外,跟日志类似,aof文件会越来越大,则可以通过执行BGREWRITEAOF命令在后台重建该文件。
我们先来看看redis如何记录命令的。
call函数是命令执行的函数(前面命令处理章节已详细介绍过该函数)。如果命令执行前后数据有修改,则server.dirty的取值会有变化。在启用了aof机制的情况下,call函数会调用feedAppendOnlyFile保存命令及其相关参数。
static void call(redisClient *c, struct redisCommand *cmd){ long long dirty; dirty = server.dirty; cmd->proc(c); dirty = server.dirty-dirty; if(server.appendonly && dirty) feedAppendOnlyFile(cmd,c->db->id,c->argv,c->argc); --- }
feedAppendOnlyFile会首先检查当前命令所处的db是否跟前一条命令执行所处db一致。若不一致,则需要发布一条选择db的select命令,然后做些命令的转换工作(代码略去)。
紧接着,将命令参数所对应的buf保存到server.aofbuf中,该参数保存了一段时间内redis执行的命令及其参数,redis会在适当的时机将其刷到磁盘上的aof文件中;然后如果有后台重建aof文件,则也将该缓冲区保存到server.bgrewritebuf中,该缓冲区保存了重建aof文件的后台进程运行时redis所执行的命令及其参数,后台进程退出时需要将这些命令保存到重建文件中。
static void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc){ --- server.aofbuf = sdscatlen(server.aofbuf,buf,sdslen(buf)); --- if(server.bgrewritechildpid != -1) server.bgrewritebuf = sdscatlen(server.bgrewritebuf,buf,sdslen(buf)); sdsfree(buf); }
我们来看看server.aofbuf会在什么时机被刷新到磁盘aof文件中。
刷新采用的是flushAppendOnlyFile函数。该函数在beforeSleep中会被调用(事件处理章节已介绍过该函数),而该函数是在处理client事件之前执行执行的(事件循环函数aeMain是先执行beforesleep,然后执行aeProcessEvents),因此,server.aofbuf中的值会在向client发送响应之前刷新到磁盘上。
flushAppendOnlyFile调用write一次性写全部server.aofbuf缓冲区中的数据,并根据配置的同步策略,调用aof_fsync(对系统同步函数fsync的保证)进行同步,这样新的命令及其参数就被附加到aof文件当中了。
static void flushAppendOnlyFile(void){ time_t now; ssize_t nwritten; --- nwritten = write(server.appendfd,server.aofbuf,sdslen(server.aofbuf)); --- sdsfree(server.aofbuf); server.aofbuf = sdsempty(); /* Fsync if needed */ now = time(NULL); if(server.appendfsync == APPENDFSYNC_ALWAYS|| (server.appendfsync == APPENDFSYNC_EVERYSEC && now-server.lastfsync > 1)) { /* aof_fsync is defined as fdatasync() for Linux in order to avoid * flushing metadata. */ aof_fsync(server.appendfd);/* Let's try to get this data on the disk */ server.lastfsync = now; } }
接下来我们看看后台如何重建aof文件。
aof重建靠调用rewriteAppendOnlyFileBackground函数完成。查看该函数的调用关系就可以知道,该函数会在收到bgrewriteaof命令后执行,也会在收到config命令并且从不使用aof机制到开启aof机制时被调用,也会在运行redis的系统作为slave时,跟master建立连接后并在serverCron函数中执行syncWithMaster时调用。
rewriteAppendOnlyFileBackground重建aof的主要逻辑如下(代码略去):
1)使用fork创建一个子进程
2)子进程调用rewriteAppendOnlyFile在一个临时文件里写能够反映当前db状态的数据和命令,
此时父进程会把这段时间内执行的能够改变当前db数据的命令放到server.bgrewritebuf中(参看前面对feedAppendOnlyFile的解释)
3)当子进程退出时,父进程收到信号,将上面的内存缓冲区中的数据flush到临时文件中,然后将临时文件rename成新的aof文件(backgroundRewriteDoneHandler)。
父进程会在serverCron函数中等待执行aof重写或者快照保存的子进程,代码如下:
/* Check if a background saving or AOF rewrite in progress terminated */ if(server.bgsavechildpid != -1||server.bgrewritechildpid != -1){ int statloc; pid_t pid; if((pid = wait3(&statloc,WNOHANG,NULL))!= 0){ if(pid == server.bgsavechildpid){ backgroundSaveDoneHandler(statloc); } else { backgroundRewriteDoneHandler(statloc); } updateDictResizePolicy(); } }
rewriteAppendOnlyFile将反映当前db状态的命令和参数写到一个临时文件中。该函数遍历db中的每条数据,redis中的db其实是一个大的hash表,每一条数据都用(key,val)来表示。从key可以知道val的类型(redis支持REDIS_STRING、REDIS_LIST、REDIS_SET、REDIS_ZSET、REDIS_HASH五种数据类型),然后解码val中的数据。写入时,按照客户端执行命令的形式写入。比如对于REDIS_STRING类型,则先写入”*3\r\n$3\r \nSET\r\n”,然后写入set的key,然后写入val;对于REDIS_LIST类型,将val强制转换为list类型后,先写入”*3\r \n$5\r\nRPUSH\r\n”,然后写入要操作的list的名字,然后写入list的第一个数据,循环前面3个步骤直到list遍历完;对于REDIS_SET类型,则对于每条数据先写入”*3\r\n$4\r\nSADD\r\n”;对于REDIS_ZSET类型,则对于每条数据先写入”*4\r\n$4\r\nZADD\r\n”;对于REDIS_HASH类型,则对于每条数据先写入”*4\r\n$4\r\nHSET\r\n”(代码简单但较琐碎,略去)。
最后我们介绍下redis启动时使用aof重建db的步骤。
启动时重建的关键是构建一个fake client,然后使用这个client向server发送从aof文件中读入的命令。
int loadAppendOnlyFile(char *filename){ --- fakeClient = createFakeClient(); while(1){ --- if(fgets(buf,sizeof(buf),fp)== NULL){ --- } // 解析buf为对应的命令及参数 // 查找命令 cmd = lookupCommand(argv[0]->ptr); --- // 执行命令 cmd->proc(fakeClient); --- } --- }
原文地址:redis源代码分析18–持久化之aof, 感谢原作者分享。

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas











Mod Redis cluster menyebarkan contoh Redis ke pelbagai pelayan melalui sharding, meningkatkan skalabilitas dan ketersediaan. Langkah -langkah pembinaan adalah seperti berikut: Buat contoh Redis ganjil dengan pelabuhan yang berbeza; Buat 3 contoh sentinel, memantau contoh redis dan failover; Konfigurasi fail konfigurasi sentinel, tambahkan pemantauan maklumat contoh dan tetapan failover; Konfigurasi fail konfigurasi contoh Redis, aktifkan mod kluster dan tentukan laluan fail maklumat kluster; Buat fail nodes.conf, yang mengandungi maklumat setiap contoh Redis; Mulakan kluster, laksanakan perintah Buat untuk membuat kluster dan tentukan bilangan replika; Log masuk ke kluster untuk melaksanakan perintah maklumat kluster untuk mengesahkan status kluster; buat

Cara Mengosongkan Data Redis: Gunakan perintah Flushall untuk membersihkan semua nilai utama. Gunakan perintah flushdb untuk membersihkan nilai utama pangkalan data yang dipilih sekarang. Gunakan Pilih untuk menukar pangkalan data, dan kemudian gunakan FlushDB untuk membersihkan pelbagai pangkalan data. Gunakan perintah DEL untuk memadam kunci tertentu. Gunakan alat REDIS-CLI untuk membersihkan data.

Untuk membaca giliran dari Redis, anda perlu mendapatkan nama giliran, membaca unsur -unsur menggunakan arahan LPOP, dan memproses barisan kosong. Langkah-langkah khusus adalah seperti berikut: Dapatkan nama giliran: Namakannya dengan awalan "giliran:" seperti "giliran: my-queue". Gunakan arahan LPOP: Keluarkan elemen dari kepala barisan dan kembalikan nilainya, seperti LPOP Queue: My-Queue. Memproses Baris kosong: Jika barisan kosong, LPOP mengembalikan nihil, dan anda boleh menyemak sama ada barisan wujud sebelum membaca elemen.

Pada sistem CentOS, anda boleh mengehadkan masa pelaksanaan skrip LUA dengan mengubah fail konfigurasi REDIS atau menggunakan arahan REDIS untuk mengelakkan skrip jahat daripada memakan terlalu banyak sumber. Kaedah 1: Ubah suai fail konfigurasi Redis dan cari fail konfigurasi Redis: Fail konfigurasi Redis biasanya terletak di /etc/redis/redis.conf. Edit Fail Konfigurasi: Buka fail konfigurasi menggunakan editor teks (seperti Vi atau nano): sudovi/etc/redis/redis.conf Tetapkan had masa pelaksanaan skrip lua: Tambah atau ubah suai baris berikut dalam fail konfigurasi untuk menetapkan masa pelaksanaan maksimum skrip lua (unit: milidor)

Gunakan alat baris perintah redis (redis-cli) untuk mengurus dan mengendalikan redis melalui langkah-langkah berikut: Sambungkan ke pelayan, tentukan alamat dan port. Hantar arahan ke pelayan menggunakan nama arahan dan parameter. Gunakan arahan bantuan untuk melihat maklumat bantuan untuk arahan tertentu. Gunakan perintah berhenti untuk keluar dari alat baris arahan.

Kaunter Redis adalah satu mekanisme yang menggunakan penyimpanan pasangan nilai utama REDIS untuk melaksanakan operasi pengiraan, termasuk langkah-langkah berikut: mewujudkan kekunci kaunter, meningkatkan tuduhan, mengurangkan tuduhan, menetapkan semula, dan mendapatkan tuduhan. Kelebihan kaunter Redis termasuk kelajuan cepat, konkurensi tinggi, ketahanan dan kesederhanaan dan kemudahan penggunaan. Ia boleh digunakan dalam senario seperti pengiraan akses pengguna, penjejakan metrik masa nyata, skor permainan dan kedudukan, dan pengiraan pemprosesan pesanan.

Terdapat dua jenis strategi tamat tempoh data REDIS: Penghapusan berkala: Imbasan berkala untuk memadamkan kunci yang telah tamat tempoh, yang boleh ditetapkan melalui parameter-cap-cap-rempah yang telah tamat tempoh dan parameter kelewatan-cap-remove-time-time. Penghapusan Lazy: Periksa kekunci yang telah tamat tempoh hanya apabila kunci dibaca atau ditulis. Mereka boleh ditetapkan melalui parameter lazon-lazy-expire-expire-expire, lazy-lazy-user-del parameter.

Dalam sistem Debian, panggilan sistem Readdir digunakan untuk membaca kandungan direktori. Jika prestasinya tidak baik, cuba strategi pengoptimuman berikut: Memudahkan bilangan fail direktori: Split direktori besar ke dalam pelbagai direktori kecil sebanyak mungkin, mengurangkan bilangan item yang diproses setiap panggilan readdir. Dayakan Caching Kandungan Direktori: Bina mekanisme cache, kemas kini cache secara teratur atau apabila kandungan direktori berubah, dan mengurangkan panggilan kerap ke Readdir. Cafh memori (seperti memcached atau redis) atau cache tempatan (seperti fail atau pangkalan data) boleh dipertimbangkan. Mengamalkan struktur data yang cekap: Sekiranya anda melaksanakan traversal direktori sendiri, pilih struktur data yang lebih cekap (seperti jadual hash dan bukannya carian linear) untuk menyimpan dan mengakses maklumat direktori
