RedisServer、RedisDB與數據字典Dict
1、關于Redis
眾所周知Redis是流行的、開源的,使用C語言開發的高性能,基于內存的key/value數據庫。它具有高效、精心設計的底層數據結構,同時支持多種數據類型(string、list、set、zset、hash、bitmap、geo、hyperloglog等),讓其能夠擁有100K+/s的讀寫性能。正是由于這些優勢讓它在眾多數據庫中脫穎而出,支撐著眾多互聯網公司的海量業務。
那么你有沒有想過,它的底層是如何運作的?本文從RedisServer的底層結構入手,并通過追溯Set指令操作過程與key的過期時間窺探一下運行原理。
2、redisServer、redisDB與數據字典dict
Redis服務是常見的c/s架構設計,即:Redis client客戶端通過與Redis Server服務端建立連接后對存儲在Redis Server端的數據進行操作。Redis Server作為一個單獨的進程運行在計算機上,其對數據進行操作的工作線程為單線程,減少了鎖開銷以及上下文的切換。
在Redis Server進程內部有一個全局變量redisServer,存儲著當前Redis Server的所有數據庫、key/value數據以及其他眾多信息,在Redis Server完全啟動并對外服務之前對其進行初始化、賦予默認值等操作,它是運行時的一個重要數據入口。
從上圖可知,Redis Server默認共擁有(0-15,自定義最大為0-255)16個數據庫(redisDB),每個數據庫包含有若干數據字典(dict),每個數據字典存儲不同意義的數據。例如:redisDb.dict 是存儲當前數據庫所有key/value的keyspace,redisDb.expires 是存儲當前數據庫所有設置了過期時間的keyspace。
查詢數據時從數據字典 redisDb.dict 中獲取,判斷/獲取key的過期時間等操作時從數據字典 redisDb.expires 中獲取。每個數據字典存儲數據時,考慮擴容等因素會有用2個 ht_table,在未擴容時數據全部存儲在 ht_table[0],否則可能在 ht_table[0]與ht_table[1] 都存有數據,ht_table 使用 bucket+鏈表(不同key在經過hash計算之后發生碰撞,會存儲在同一個bucket的鏈表中)的形式存儲具體的key/value。
3、redis client如何與數據庫建立聯系
每當redis client客戶端與Redis Server服務端建立連接之后,Redis Server為該客戶端創建結構體 client 用于存儲客戶端相關信息,其中就包含客戶端所使用的數據庫(默認為0,可以通過select指令選擇其他數據庫)。然后Redis Server服務端通過雙向鏈表把這些client連接起來,存儲到全局變量redisServer的clients字段中。就這樣redis client客戶端與Redis數據庫建立了聯系,后續就能直接找到對應數據庫進行讀、寫等操作。
每當redis client客戶端發送命令到服務端之后,Redis Server通過 client.db 找到對應的數據庫,然后進行相關操作。
4、Set指令執行過程
5、小結
本文通過講解 redisServer、redisDB與數據字典dict之間的聯系,同時通過分析Set指令(v7.0 版本目前有240個命令)的執行過程,可以對其底層原理有更深的認知。
曾經有一位技術大咖說過:若想學習一個好的開源項目,那么首推Redis,無論從代碼功能、變量聲明,甚至從注釋來看都無可挑剔。