Redis Source Code Analysis (1)--initialization

Source: Internet
Author: User
Tags epoll redis version unix domain socket

Recently have been looking at the source of Redis, ready to the source of understanding and reading experience recorded, to avoid forgetting and can share with you, talk about. Look at the code is very simple, directly from the main function to walk, first look at the initialization process.One of the most important data structures in Redis is Redis_server, which creates a global variable server for this structure, representing the current Redis configuration and state, and most of the initialization work is to set the properties of the structure.The initialization work can be divided into 4 parts:1) Set default value for server2) parsing command-line arguments3) parsing the configuration file4) Initializing the serverWhen initialization is complete, the event loop is started to receive and service requests. The following steps parse the main function without focusing on sentinel logic.(1) The first part of the main function, primarily for simple initialization, including setting collate, setting the random number seed, and then calling Initserverconfig () to set the default value for the global variable server.
struct Timeval TV; /* We need to initialize our libraries, and the server configuration. */#ifdef Init_setproctitle_replacement spt_init (argc, argv); #endif//<MM>//Use environment variables to initialize string comparisons//</mm    > setlocale (Lc_collate, "");    Zmalloc_enable_thread_safeness ();    Zmalloc_set_oom_handler (Redisoutofmemoryhandler);    <MM>//Set the seed of random, then generate random run ID, all join Process ID factor//</MM> Srand (Time (NULL) ^getpid ());    Gettimeofday (&tv,null);    Dictsethashfunctionseed (Tv.tv_sec^tv.tv_usec^getpid ());    Server.sentinel_mode = Checkforsentinelmode (ARGC,ARGV);    <MM>//Set initial default value for Redisserver//</MM> initserverconfig (); /* We need to Init Sentinel right now as parsing the configuration file * In Sentinel mode would have the effect of pop Ulating the Sentinel * data structures with master nodes to monitor.        */if (Server.sentinel_mode) {initsentinelconfig ();    Initsentinel (); }
In the Initserverconfig function, most of the default values are set on the server's properties, and part of the command table initialization for Redis is called by the populatecommandtable function. Global variable rediscommandtable is an array of type Rediscommand that holds all the commands that Redis supports. Server.commands is a dict that holds the command name to Rediscommand mappings. The Populatecommandtable function iterates through the global rediscommandtable table, inserts each command into Server.commands, and sets its flags according to the properties of each command.The Rediscommand structure is as follows:
struct    Rediscommand {//command name, in the Server.commands command table, with command fame key char *name;    Command processing function Rediscommandproc *proc;    The operand of the command, >0 indicates the exact operand, and <0 indicates at least arity operand int arity; The character representation of the token bit, mainly used for initializing the command table char *sflags; /* Flags As String representation, one char per flag.    *///attribute tag bit, bitwise, specifies the type of command int flags; /* The actual flags, obtained from the ' Sflags ' field. *////The following 4 properties are used to resolve a key from a client request, such as Mset K1, v1, K2, v2 .../* Use a function to determine keys arguments in a comman D line.    */Redisgetkeysproc *getkeys_proc; /* What keys should is loaded in background when calling this command? */int firstkey;  /* The first argument that ' s a key (0 = no keys) */int lastkey;  /* The last argument that ' s a key */int keystep; /* The step between first and last key *//statistical information long long microseconds, calls;}; 
Rediscommand has the attribute proc, which represents the command handler function. When processing a client request, get to the command name, get to Rediscommand from the Server.commands dictionary, and then callback its proc function.
(2) The command-line parsing section, which mainly resolves the command line configuration options and the configuration entries passed through the command line. The configuration file is then parsed, mainly through two functions:Loadserverconfig: The complete function is simple, which is to read the contents of the file into a string. and appends the incoming configuration item through the command line to the string.loadserverconfigfromstring: Resolves the configuration item from the string and sets the related properties of the server.When this step is complete, the simple properties (integers, strings) in the server are basically set to complete.(3) Next is the initialization section. Set as daemon, create PID file, set process title and print startup log. The most important of these is the Initserver function initializes the underlying data structure. After initialization, the data needs to be loaded from the disk, either an RDB or a aof.
    <MM>/Daemon process//</MM> if (server.daemonize) daemonize ();    Initserver ();    <MM>//Create PID File//</MM> if (server.daemonize) createpidfile ();    <MM>//Set process name//</MM> Redissetproctitle (argv[0]);    <MM>//Print start-up Log//</MM> Redisasciiart (); if (!server.sentinel_mode) {/* things not needed when running in Sentinel mode. */Redislog (redis_warning, "    Server started, Redis version "Redis_version");    #ifdef __linux__ linuxovercommitmemorywarning ();        #endif//<MM>//Load data from disk, RDB or aof//</MM> loaddatafromdisk ();  if (Server.ipfd_count > 0) redislog (redis_notice, "The server is now a ready-to-accept connections on port%d",        Server.port); if (Server.sofd > 0) redislog (redis_notice, "The server is now a ready-to-accept connections at%s", Server.uni    Xsocket); } else {sentinelisrunning ();    }/* Warning the user about suspicious maxmemory setting. */if (server.maxmemory > 0 && server.maxmemory < 1024*1024) {Redislog (redis_warning, "warning:yo U specified a maxmemory value that is less than 1MB (current value is%llu bytes).    Was you sure the is really want? ", server.maxmemory); }
Initserverconfig the server's integer type, String type of property settings, Initserver mainly to the composite data structure list, dict and so on initialization, and create an event loop, initialize the listener socket and so on. Here's a look at the Initserver function:
First, register the signal processing function.
    Int J;    Signal (SIGHUP, sig_ign);    Signal (Sigpipe, sig_ign);    Setupsignalhandlers ();
if the setting turns on syslog, it is initialized.
    if (server.syslog_enabled) {        openlog (server.syslog_ident, Log_pid | Log_ndelay | Log_nowait,            server.syslog_facility);    }
initializing client-related data structures。 Redis organizes all connected clients, slave, and Monitor's clients into linked lists, which are primarily created in these lists.
    Server.current_client = NULL;    Server.clients = Listcreate ();    Server.clients_to_close = Listcreate ();    Server.slaves = Listcreate ();    Server.monitors = Listcreate ();    Server.slaveseldb =-1; /* Force to emit the first SELECT command. *    /server.unblocked_clients = Listcreate ();    Server.ready_keys = Listcreate ();
A constant pool is created for frequently used objects in Redis to avoid the overhead of frequent creation and recycling. These objects include frequently used response content as well as integers less than 10000, as well as response headers that represent the number of bulk, and bulk-length response headers, which only include lengths less than 32.
    <MM>    //create constant pool to avoid frequent creation    //</MM>    createsharedobjects ();
To adjust the opening descriptor limit, you need to call Getrlimit and Setrlimit.
    <MM>//    According to maxclients configuration, adjust open file descriptor limit    //</MM>    adjustopenfileslimit ();
Initializes the event loop, which is described in the event Loop section. The DB array is then created based on the configuration.
    <MM>    //Initialize event loop, as Epoll implementation, calls Epoll_create to create Epoll FD    //</MM>    Server.el = Aecreateeventloop (SERVER.MAXCLIENTS+REDIS_EVENTLOOP_FDSET_INCR);    server.db = Zmalloc (sizeof (REDISDB) *server.dbnum);
The initial listener socket is called socket, bind, listen, and so on, and the socket is set to non-blocking. If a UNIX domain socket is configured, the corresponding initialization is also done.
The next code initializes each db in the server.db array, primarily creating the related Dict. Then about the initialization of PubSub, RDB, AOF, replication related data structures. The code will not be posted.The Timer event Servercron is then added and executed after the event loop 1ms is started. The event loop in Redis is the only one that executes once every 0.1s (approximately), primarily handling asynchronous tasks such as clearing expired keys, updating statistics, and check for RDB, aof subprocess status, The Clientcron and Databasecron are then called.
    <MM>    //Register Servercrom time event, start event loop 1ms and execute    //</MM>/    * Create the Servercron () Hat's our main-to-process     * background operations. *    /if (Aecreatetimeevent (Server.el, 1, Servercron, NULL, NUL L) = = Ae_err) {        redispanic ("Can ' t create the Servercron time event.");        Exit (1);    }
Add all listening sockets to the event loop。 You can see that there will be Accepttcphandler processing the client connection establishment.
    <MM>//    Add File event for all listener sockets, event handler is Accepttcphandler used to process connection creation    //</MM>/    * Create an Event handler for accepting new connections in TCP and Unix     * domain sockets. *    /for (j = 0; J < Server.ipfd_co Unt J + +) {        if (aecreatefileevent (Server.el, Server.ipfd[j], ae_readable,            accepttcphandler,null) = = Ae_err)            {                redispanic (                    "Unrecoverable Error creating SERVER.IPFD file event.");            }    }    if (Server.sofd > 0 && aecreatefileevent (server.el,server.sofd,ae_readable,        acceptunixhandler,null) = = Ae_err) redispanic ("Unrecoverable Error creating SERVER.SOFD file event.");
if AoF is turned on, create the aof file。
    /* Open The AOF file if needed. *    /if (server.aof_state = = redis_aof_on) {        server.aof_fd = open (Server.aof_filename,                               o_wronly| o_append| o_creat,0644);        if (server.aof_fd = =-1) {            redislog (redis_warning, "Can ' t open the Append-only file:%s",                strerror (errno));            Exit (1);        }    }
Finally, the MaxMemory configuration is validated and set, the Lua script is initialized, slow log and latency monitor, and the final bioinit initializes the asynchronous IO thread. Redis is a single thread, and for heavy IO operations, such as AoF's Fsync, calls are made by asynchronous threads, avoiding the event loops that block the main thread. The above is the Initserver function.
    /* Instances limited to 4GB of address space, so if there is     * No explicit limit in the user provided CONFI Guration we set a limit     * at 3 GB using MaxMemory with ' noeviction ' policy '. This avoids     * useless crashes of the Redis instance for out of memory. * *    if (server.arch_bits = = && SE Rver.maxmemory = = 0) {        redislog (redis_warning, "warning:32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with ' noeviction ' policy now. ");        Server.maxmemory = 3072ll* (1024*1024); /* 3 GB */        server.maxmemory_policy = redis_maxmemory_no_eviction;    }    Replicationscriptcacheinit ();    Scriptinginit ();    Slowloginit ();    Latencymonitorinit ();    <MM>    //Initialize asynchronous blocking IO processing thread    //</MM>    bioinit ();
(4) The last of the main function is to start the event loop. In each iteration of the event loop, the Beforesleep function is called before sleep for some asynchronous processing. The Beforesleep function is set here first and then the Aemain event loop is started. After exiting from the event loop, clean up the event loop and exit.
    Aesetbeforesleepproc (server.el,beforesleep);    <MM>    //Open Event loop    //</MM>    Aemain (server.el);    Aedeleteeventloop (Server.el);    return 0;
these are the initial and startup processes of Redis. Overall, relatively simple, compared to nginx configuration file parsing, module initialization, process initialization is much simpler, read it will not be too laborious.the next article describes the event loop.


Redis Source Code Analysis (1)--initialization

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.