在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 大數(shù)據(jù)/ Redis 日志和斷言
Redis 數(shù)據(jù)淘汰機(jī)制
積分排行榜
小剖 Memcache
Redis 數(shù)據(jù)結(jié)構(gòu) intset
分布式鎖
從哪里開(kāi)始讀起,怎么讀
Redis 數(shù)據(jù)結(jié)構(gòu) dict
不在浮沙筑高臺(tái)
Redis 集群(上)
Redis 監(jiān)視器
源碼閱讀工具
Redis 日志和斷言
內(nèi)存數(shù)據(jù)管理
Redis 數(shù)據(jù)結(jié)構(gòu)綜述
源碼日志
Web 服務(wù)器存儲(chǔ) session
消息中間件
Redis 與 Lua 腳本
什么樣的源代碼適合閱讀
Redis 數(shù)據(jù)結(jié)構(gòu) sds
Memcached slab 分配策略
訂閱發(fā)布機(jī)制
Redis 是如何提供服務(wù)的
Redis 事務(wù)機(jī)制
Redis 集群(下)
主從復(fù)制
Redis 應(yīng)用
RDB 持久化策略
Redis 數(shù)據(jù)遷移
Redis 事件驅(qū)動(dòng)詳解
初探 Redis
Redis 與 Memcache
AOF 持久化策略
Redis 數(shù)據(jù)結(jié)構(gòu) redisOb
作者簡(jiǎn)介
Redis 數(shù)據(jù)結(jié)構(gòu) ziplist
Redis 數(shù)據(jù)結(jié)構(gòu) skiplist
Redis 哨兵機(jī)制

Redis 日志和斷言

Redis 日志

linux 的世界里,最好用的調(diào)試工具不是 gdb,而是日志和 printf。日志在一個(gè)軟件系統(tǒng)中是非常常見(jiàn)的,一個(gè)關(guān)鍵的作用即定位錯(cuò)誤,當(dāng)系統(tǒng)出問(wèn)題首先想到就是日志,查看日志能快速定位問(wèn)題。Redis 中的日志模塊較為簡(jiǎn)單。我們?cè)?Redis 源碼中,到處都可以見(jiàn)到 redisLog()。

通常,日志會(huì)分為幾個(gè)級(jí)別。在 Redis 中 5 個(gè)日志級(jí)別,在 redis.h 文件中有定義:

/* Log levels */
#define REDIS_DEBUG 0 // 調(diào)試級(jí)別,這一級(jí)別產(chǎn)生最多的日志信息
#define REDIS_VERBOSE 1
#define REDIS_NOTICE 2
#define REDIS_WARNING 3
#define REDIS_LOG_RAW (1<<10) /* Modifier to log without timestamp */
#define REDIS_DEFAULT_VERBOSITY REDIS_NOTICE

服務(wù)器的配置結(jié)構(gòu)體中,struct redisServer.verbosity 是用來(lái)設(shè)定日志級(jí)別的,譬如將日志級(jí)別設(shè)定為REDIS_NOTICE 后,代碼中 REDIS_VERBOSE 和REDIS_DEBUG 級(jí)別的日志都不會(huì)被打印。

日志級(jí)別值越是低,日志級(jí)別越高,產(chǎn)生了日志也就越多,開(kāi)發(fā)人員在產(chǎn)品上線之前會(huì)將日志級(jí)別調(diào)至最低,方便發(fā)現(xiàn)定位或發(fā)現(xiàn)潛在的問(wèn)題。而上線之后,可以將志級(jí)別降低,減少調(diào)試日志。如果日志級(jí)別過(guò)高,則日志量大,可能會(huì)對(duì)線上的服務(wù)產(chǎn)生影響,因?yàn)閷?xiě)日志就是寫(xiě)文件操作,系統(tǒng)調(diào)用是要消耗時(shí)間的。

日志是想要記錄某一個(gè)時(shí)間點(diǎn),在哪里發(fā)送了什么事情,以方便出現(xiàn)問(wèn)題的時(shí)候,恢復(fù)現(xiàn)場(chǎng),快速定位問(wèn)題所在。“某一時(shí)間點(diǎn)”即添加時(shí)間戳;“在哪里”即程序執(zhí)行的位置,對(duì)應(yīng)的是源碼的文件,行號(hào)函數(shù)等;“發(fā)生了什么事情”即記錄一些關(guān)鍵數(shù)據(jù)。

// redis 日志函數(shù),會(huì)將給定的數(shù)據(jù)寫(xiě)入日志文件,和常用的printf 函數(shù)用法差不多
void redisLog(int level, const char *fmt, ...) {
    va_list ap;
    char msg[REDIS_MAX_LOGMSG_LEN];
    // 如果日志級(jí)別小于預(yù)設(shè)的日志級(jí)別,直接返回
    if ((level&0xff) < server.verbosity) return;
    va_start(ap, fmt);
    vsnprintf(msg, sizeof(msg), fmt, ap);
    va_end(ap);
    // redisLogRaw() 函數(shù)將給定的信息,在增加時(shí)間戳和進(jìn)程id 后寫(xiě)入日志文件
    redisLogRaw(level,msg);
}

Redis 斷言

為什么需要斷言???????> TODO 當(dāng)你認(rèn)為某些事情在正常情況下不可能出現(xiàn),應(yīng)盡可能結(jié)束任務(wù),而不是捕捉錯(cuò)誤,嘗試挽救。同樣在西加加里,使用 try…catch() 會(huì)讓程序的邏輯變亂,甚至讓程序的行為變得不可預(yù)測(cè),大膽的使用斷言吧。

Redis 中不僅僅實(shí)現(xiàn)了斷言,且在斷言失敗的時(shí)候會(huì)打印一些關(guān)鍵的信息。

在 Redis.h 中定義了兩個(gè)斷言相關(guān)的宏:

#define redisAssertWithInfo(_c,_o,_e) \
    ((_e)?(void)0 : \
    (_redisAssertWithInfo(_c,_o,#_e,__FILE__,__LINE__),_exit(1)))
#define redisAssert(_e) \
    ((_e)?(void)0 : \
    (_redisAssert(#_e,__FILE__,__LINE__),_exit(1)))

如果斷言為真,執(zhí)行一個(gè)空操作;斷言為假,會(huì)打印關(guān)鍵的信息。

_redisAssert() 函數(shù)會(huì)記錄斷言發(fā)生的錯(cuò)誤信息,文件名和行號(hào)

void _redisAssert(char *estr, char *file, int line) {
    // 向日志文件中寫(xiě)入BUG 頭部
    bugReportStart();
    // 將文件名,行號(hào),錯(cuò)誤信息寫(xiě)入日志
    redisLog(REDIS_WARNING,"=== ASSERTION FAILED ===");
    redisLog(REDIS_WARNING,"==> %s:%d '%s' is not true",file,line,estr);
    // 如果需要,可以記錄錯(cuò)誤信息,文件名和行號(hào),以便在進(jìn)程崩潰后調(diào)試(gdb core?)
#ifdef HAVE_BACKTRACE
    server.assert_failed = estr;
    server.assert_file = file;
    server.assert_line = line;
    redisLog(REDIS_WARNING,"(forcing SIGSEGV to print the bug report.)");
#endif
    // 強(qiáng)制segmentation fault。無(wú)效的內(nèi)存訪問(wèn),可以產(chǎn)生SIGSEGV,如此會(huì)
    // 產(chǎn)生coredump 文件以供進(jìn)程崩潰后調(diào)試使用
    *((char*)-1) = 'x';
}

這有個(gè)小有意思的語(yǔ)句:*((char*)-1) = ’x’;(char *)-1表示指向地址值為 -1 的指針,它所指向的內(nèi)存肯定是非法的,對(duì)非法內(nèi)存的操作會(huì)觸發(fā) SIGSEGV 信號(hào),進(jìn)程結(jié)束后會(huì)產(chǎn)生 coredump 文件,方便調(diào)試使用。使用gdb、可執(zhí)行文件和 coredump 文件能快速定位問(wèn)題所在,即使進(jìn)程已經(jīng)崩潰了。

_redisAssertWithInfo() 函數(shù)會(huì)打印 Redis 服務(wù)器當(dāng)前服務(wù)的客戶端和某個(gè)關(guān)鍵 Redis 對(duì)象的信息,具體請(qǐng)參看源碼,在這不展開(kāi)了。