Implementation of redis Snapshot

Source: Internet
Author: User

Redis Snapshot

In the previous article, we learned how to implement redis Aof. In this article, we will learn another persistence method of redis: snapshot ).
Like in the previous article, we will first introduce the relevant parameters, and then introduce the application scenarios in sequence.

1. Configure Parameters
Save <seconds> <changes>: the number of update operations in seconds relative to a database. At this time, a save operation is performed. You can set multiple conditions, any of them will be saved once. The following configuration is called a time change condition.
Rdbcompression yes: whether to perform the compression operation
Dbfilename dump. RDB: name of the data file
DIR/u01/Xiangzhong/redis-2.4.2/data: location where the above file is saved

2. Use Cases
With the Save <seconds> <changes> parameter above, we can know that the Save RDB operation will be executed when this condition is triggered. So let's take a look at this process first.
2.1 save <seconds> <changes> condition-triggered automatic operation
This process is determined in servercron

/* If there is not a background saving in progress check if * We Have To save now */For (j = 0; j <server. saveparamslen; j ++) {// determine the total number of time change conditions. This condition consists of three parts. When the system starts, initserverconfig initializes three [(60*60, 1 ), (300,100), (60,)]; then load the configuration file loadserverconfig; finally, the client adds conditions through commands; they are saved to the server. in the saveparams dynamic array, the overwrite is not de-duplicated during append, but the data is not too large, so the effect is not big. struct saveparam * sp = server. saveparams + J; If (server. dirty> = Sp-> Changes & now-server.lastsave> SP-> seconds) {// here is a simple redislog (redis_notice, "% d changes in % d seconds. saving... ", SP-> changes, SP-> seconds); rdbsavebackground (server. dbfilename); // after the child process is generated, perform the write operation break ;}}

Here we will not introduce the rdbsavebackground function, but will directly introduce the processing of rdbsave for sub-processes:

Int rdbsave (char * filename ){... snprintf (tmpfile, 256, "Temp-% d. RDB ", (INT) getpid (); // generate a new temporary file fp = fopen (tmpfile," W "); If (fwrite (" redis0002 ", 9, 1, FP) = 0) goto werr; For (j = 0; j <server. dbnum; j ++) {redisdb * DB = server. DB + J; dict * D = DB-> dict; If (dictsize (d) = 0) continue; DI = dictgetsafeiterator (d); // write the select dB command, only the encoding method is used here, not the readable character command if (rdbsavetype (FP, redis_selectdb) =-1) g Oto werr; If (rdbsavelen (FP, j) =-1) goto werr; // dB ID while (DE = dictnext (DI ))! = NULL) {// retrieve all records of all tables in the database. Entry SDS keystr = dictgetentrykey (de); // obtain the key value robj key, * o = dictgetentryval (de); // obtain the value time_t expiretime; initstaticstringobject (Key, keystr); // there are two possibilities for the key: encode: raw. Raw is directly used for int, only data can be encoded as Int. Therefore, raw is safe and reliable. expiretime = getexpire (dB, & Key); If (expiretime! =-1) {// determines whether the key has expired. If the key has expired, skip if (expiretime <now) continue. If (rdbsavetype (FP, redis_expiretime) =-1) goto werr; If (rdbsavetime (FP, expiretime) =-1) goto werr;} If (! Server. vm_enabled | o-> storage = redis_vm_memory | o-> storage = redis_vm_swapping) {int otype = getobjectsavetype (o); // type of value obtained/* save type, key, value */If (rdbsavetype (FP, otype) =-1) goto werr; If (rdbsavestringobject (FP, & Key) =-1) goto werr; if (rdbsaveobject (FP, O) =-1) goto werr ;}...} // end while dict entry dictreleaseiterator (DI);} // end for DB if (rdbsavetype (FP, redis_eof) =-1) goto werr; fflush (FP ); fsync (fileno (FP); fclose (FP); rename (tmpfile, filename); server. dirty = 0; // It does not work for updating the values of sub-processes. However, if you use the Save command, it is performed in the main thread, so you must update the server. lastsave = Time (null );...}

This function is much simpler than the rewriteappendonlyfile of aof, the Comment inside is also very clear, the type and encode of value can refer to: http://www.w3ccollege.org/redis/redis-internal/redis-memory-storage-structure-analysis-2.html
When the background sub-process ends, the main thread wait the signal in the servercron (this is the same as the aof time). Let's take a look at the signal processing function backgroundsavedonehandler.

Server. Dirty = server. Dirty-server. dirty_before_bgsave; // update dirty server. lastsave = Time (null); server. bgsavechildpid =-1; updateslaveswaitingbgsave (exitcode = 0? Redis_ OK: redis_err); // This is related to the repl slave.

2.2 Client Command triggering
The above describes the system's automatic detection of time change conditions to complete the Save RDB process. Next we will introduce the other two cases which are triggered by the client through commands: Save and bgsave.
A. Save
The callback function of this command is savecommand.

Void savecommand (redisclient * c) {// if there is a process behind the save, it is obviously no longer needed. In addition, this function is implemented by calling rdbsave. If (server. bgsavechildpid! =-1) {addreplyerror (C, "background save already in progress"); return;} If (rdbsave (server. dbfilename) = redis_ OK) {addreply (C, shared. OK);} else {addreply (C, shared. err );}}

Note: This method is used to execute the Save RDB operation in the main thread, so it will block the work of the main thread. Therefore, it is generally not recommended to use this command, but the following command.

B. bgsave
The callback function of this command is bgsavecommand, which is also implemented by calling rdbsavebackground. In fact, this process is the same as that of the preceding server when determining the time to change the condition, the latter is enforced by the client through commands, rather than waiting until the conditions are met as in the former. So we will not go into details here.

3. Summary
There are three application scenarios for redis snapshot: one is to check whether the conditions for changing the time are met when running servercron each time. If yes, a background sub-process will be created to perform memory data to dump. RDB file writing process: Write the memory data to a tempfile, and then rename (that is, save the entire memory data every time, instead of modifying the updated data); the client sends the Save command, this is executed in the main thread, so the response of the main thread to the file event is blocked. The last one is similar to the first one, but it is implemented by sending bgsave via the client. In addition, it is called snapshot because the Fork sub-process and the parent process temporarily share the memory address space through copy-on-write, without affecting the parent process.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.