redis-server启动但进程里没有_Redis——服务器的启动过程
這一節,我們研究的目光聚焦在redis服務器的啟動過程。具體研究啟動過程做了哪些工作。
啟動redis命令:src/redis-server redis.conf 30408:C 13 Jan 2021 17:29:52.662 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 30408:C 13 Jan 2021 17:29:52.662 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=30408, just started 30408:C 13 Jan 2021 17:29:52.662 # Configuration loaded 第二步 加載配置_._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit.-`` .-```. ```/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 redis服務器的端口號| `-._ `._ / _.-' | PID: 30408 redis的進程號`-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 30408:M 13 Jan 2021 17:29:52.664 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 30408:M 13 Jan 2021 17:29:52.664 # Server initialized 第三步 執行initServer函數,初始化服務器的數據結構 30408:M 13 Jan 2021 17:29:52.664 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. 30408:M 13 Jan 2021 17:29:52.664 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. 30408:M 13 Jan 2021 17:29:52.664 * DB loaded from disk: 0.000 seconds 第四步操作結束后,會打印 30408:M 13 Jan 2021 17:29:52.664 * Ready to accept connections 第五步操作結束后,會打印第一步:創建一個redisServer的實例變量,并且為實例中的各種變量設置默認值。(本質就是調用initServerConfig函數)
initServerConfig函數的工作有:
1、設置服務器的運行id
2、設置服務器的默認運行頻率
3、設置服務器的默認配置文件路徑
4、設置服務器的運行架構
5、設置服務器的默認端口號
6、設置RDB持久化條件和AOF持久化條件
7、初始化服務器的LRU時鐘
8、創建命令表(但沒創建server.clients鏈表等其他數據結構)
第二步:載入配置選項,就是加入redis.cong文件或者命令參數,用來替換第一步設置的默認值。
30408:C 13 Jan 2021 17:29:52.662 # Configuration loaded第三步:初始化服務器的數據結構:比如server.clients鏈表,server.db數組,server.slowlog。現在才初始化數據結構的原因是,服務器必須先載入配置選項后,才進行初始化數據結構,否則的話,就要重新修改數據結構了。(本質就是調用了InitServer函數),除了創建數據結構,還要設置進程信號處理器(就是用來檢測服務器的退出信號,當執行完initServer函數后,就會打印redis的logo,版本信息等)
_._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit.-`` .-```. ```/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 redis服務器的端口號| `-._ `._ / _.-' | PID: 30408 redis的進程號`-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 30408:M 13 Jan 2021 17:29:52.664 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 30408:M 13 Jan 2021 17:29:52.664 # Server initialized第四步:還原數據庫狀態。就是加載RDB文件或AOF文件,進行還原數據庫的狀態。加載的機制是:首先先加載aof文件,有aof文件,加載完后就結束加載流程。沒AOF文件,那就去加載RDB文件。加載完RDB文件,就結束加載流程。還原數據庫狀態后,黑窗口會打印以下這段信息:
30408:M 13 Jan 2021 17:29:52.664 * DB loaded from disk: 0.000 seconds第五步:執行事件循環,就是進入執行流程了,可以接受客戶端的連接和請求了。黑窗口會打印一下這段信息:
30408:M 13 Jan 2021 17:29:52.664 * Ready to accept connections接下來我們對照redis的server.c源碼里面的main函數進行分析:
具體源碼文件鏈接:https://github.com/redis/redis/blob/5.0/src/server.c
int main(int argc, char **argv) {第一步:省略很多代碼...initServerConfig();第二步:省略很多代碼...loadServerConfig(server.configfile, config_from_stdin, options);第三步:省略很多代碼...initServer();第四步:省略很多代碼...loadDataFromDisk();serverLog(LL_NOTICE,"DB loaded from disk: %.3f seconds",(float)(ustime()-start)/1000000);第五步:省略很多代碼...serverLog(LL_NOTICE,"Ready to accept connections"); }接下來看具體每一個函數的代碼:
initServerConfig();
void initServerConfig(void) {int j;pthread_mutex_init(&server.next_client_id_mutex,NULL);pthread_mutex_init(&server.lruclock_mutex,NULL);pthread_mutex_init(&server.unixtime_mutex,NULL);updateCachedTime(1);getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);server.runid[CONFIG_RUN_ID_SIZE] = '0'; //運行idchangeReplicationId();clearReplicationId2();server.timezone = getTimeZone(); /* Initialized by tzset(). */ 時間server.configfile = NULL;server.executable = NULL;server.hz = server.config_hz = CONFIG_DEFAULT_HZ; 默認頻率,這個用來控制serverCron函數,每秒執行的次數server.dynamic_hz = CONFIG_DEFAULT_DYNAMIC_HZ;server.arch_bits = (sizeof(long) == 8) ? 64 : 32;server.port = CONFIG_DEFAULT_SERVER_PORT; 端口server.tcp_backlog = CONFIG_DEFAULT_TCP_BACKLOG;server.bindaddr_count = 0;...省略很多代碼,真的超級無敵多,但都是初始化默認值}initServer()
void initServer(void) {int j;signal(SIGHUP, SIG_IGN);signal(SIGPIPE, SIG_IGN);setupSignalHandlers();if (server.syslog_enabled) {openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,server.syslog_facility);}server.hz = server.config_hz; 頻率server.pid = getpid(); 進程idserver.current_client = NULL;server.fixed_time_expire = 0;server.clients = listCreate();server.clients_index = raxNew();server.clients_to_close = listCreate();server.slaves = listCreate();server.monitors = listCreate();server.clients_pending_write = listCreate();server.slaveseldb = -1; /* Force to emit the first SELECT command. */server.unblocked_clients = listCreate();server.ready_keys = listCreate();server.clients_waiting_acks = listCreate();server.get_ack_from_slaves = 0;server.clients_paused = 0;server.system_memory_size = zmalloc_get_memory_size();...省略很多代碼}loadDataFromDisk
void loadDataFromDisk(void) {long long start = ustime();if (server.aof_state == AOF_ON) { 首先,判斷AOF是否開啟,如果開啟,就嘗試加載AOF文件if (loadAppendOnlyFile(server.aof_filename) == C_OK)serverLog(LL_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);} else {rdbSaveInfo rsi = RDB_SAVE_INFO_INIT; 加載RDB文件if (rdbLoad(server.rdb_filename,&rsi) == C_OK) {serverLog(LL_NOTICE,"DB loaded from disk: %.3f seconds",(float)(ustime()-start)/1000000); 這個就是打印出來的日志/* Restore the replication ID / offset from the RDB file. */if ((server.masterhost ||(server.cluster_enabled &&nodeIsSlave(server.cluster->myself))) &&rsi.repl_id_is_set &&rsi.repl_offset != -1 &&/* Note that older implementations may save a repl_stream_db* of -1 inside the RDB file in a wrong way, see more* information in function rdbPopulateSaveInfo. */rsi.repl_stream_db != -1){memcpy(server.replid,rsi.repl_id,sizeof(server.replid));server.master_repl_offset = rsi.repl_offset;/* If we are a slave, create a cached master from this* information, in order to allow partial resynchronizations* with masters. */replicationCacheMasterUsingMyself();selectDb(server.cached_master,rsi.repl_stream_db);}} else if (errno != ENOENT) {serverLog(LL_WARNING,"Fatal error loading the DB: %s. Exiting.",strerror(errno));exit(1);}} }總結,上述對照著redis的源代碼,來深入了解了Redis服務器的啟動過程,具體的細節,都可以在代碼中找到。
1、賦值初始值;
2、加載配置文件;
3、創建數據結構;
4、還原數據庫數據;
5、等待事件發生。
下一篇文章,介紹reids的執行過程及其細節。
公眾號:大頭菜技術
總結
以上是生活随笔為你收集整理的redis-server启动但进程里没有_Redis——服务器的启动过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue判断a是否可点击_判断 a 和 b
- 下一篇: yspider爬取数据导入mysql_爬