C++實現迷宮生成與解決
Redis 是一個鍵值對(key-value pair)資料庫伺服器, 伺服器中的每個資料庫都由一個 redis.h/redisDb
結構表示, 其中, redisDb
結構的dict
字典儲存了資料庫中的所有鍵值對, 我們將這個字典稱為鍵空間(key space):
typedef struct redisDb { // ... // 資料庫鍵空間,儲存著資料庫中的所有鍵值對 dict *dict; // ... } redisDb;
鍵空間和使用者所見的資料庫是直接對應的:
- 鍵空間的鍵也就是資料庫的鍵, 每個鍵都是一個字串物件。
- 鍵空間的值也就是資料庫的值, 每個值可以是字串物件、列表物件、雜湊表物件、集合物件和有序集合物件在內的任意一種 Redis 物件。
舉個例子, 如果我們在空白的資料庫中執行以下命令:
redis> SET message "hello world" OK redis> RPUSH alphabet "a" "b" "c" (integer) 3 redis> HSET book name "Redis in Action" (integer) 1 redis> HSET book author "Josiah L. Carlson" (integer) 1 redis> HSET book publisher "Manning" (integer) 1
那麼在這些命令執行之後, 資料庫的鍵空間將會是圖 IMAGE_DB_EXAMPLE 所展示的樣子:
alphabet
是一個列表鍵, 鍵的名字是一個包含字串"alphabet"
的字串物件, 鍵的值則是一個包含三個元素的列表物件。book
是一個雜湊表鍵, 鍵的名字是一個包含字串"book"
的字串物件, 鍵的值則是一個包含三個鍵值對的雜湊表物件。message
是一個字串鍵, 鍵的名字是一個包含字串"message"
的字串物件, 鍵的值則是一個包含字串"hello world"
的字串物件。
因為資料庫的鍵空間是一個字典, 所以所有針對資料庫的操作 —— 比如新增一個鍵值對到資料庫, 或者從資料庫中刪除一個鍵值對, 又或者在資料庫中獲取某個鍵值對, 等等, 實際上都是通過對鍵空間字典進行操作來實現的, 以下幾個小節將分別介紹資料庫的新增、刪除、更新、取值等操作的實現原理。
新增新鍵
新增一個新鍵值對到資料庫, 實際上就是將一個新鍵值對新增到鍵空間字典裡面, 其中鍵為字串物件, 而值則為任意一種型別的 Redis 物件。
舉個例子, 如果鍵空間當前的狀態如圖 IMAGE_DB_EXAMPLE 所示, 那麼在執行以下命令之後:
redis> SET date "2013.12.1" OK
鍵空間將新增一個新的鍵值對, 這個新鍵值對的鍵是一個包含字串 "date"
的字串物件, 而鍵值對的值則是一個包含字串 "2013.12.1"
的字串物件, 如圖 IMAGE_DB_AFTER_ADD_NEW_KEY 所示。
再舉個例子, 如果我們繼續執行以下命令:
redis> HSET book page 320 (integer) 1
那麼鍵空間中 book
鍵的值物件(一個雜湊物件)將被更新, 新的鍵值對 page
和 320
會被新增到值物件裡面, 如圖 IMAGE_UPDATE_BY_HSET 所示。
因為資料庫的鍵空間是一個字典, 所以所有針對資料庫的操作 —— 比如新增一個鍵值對到資料庫, 或者從資料庫中刪除一個鍵值對, 又或者在資料庫中獲取某個鍵值對, 等等, 實際上都是通過對鍵空間字典進行操作來實現的, 以下幾個小節將分別介紹資料庫的新增、刪除、更新、取值等操作的實現原理。
新增新鍵
新增一個新鍵值對到資料庫, 實際上就是將一個新鍵值對新增到鍵空間字典裡面, 其中鍵為字串物件, 而值則為任意一種型別的 Redis 物件。
舉個例子, 如果鍵空間當前的狀態如圖 IMAGE_DB_EXAMPLE 所示, 那麼在執行以下命令之後:
redis> SET date "2013.12.1" OK
鍵空間將新增一個新的鍵值對, 這個新鍵值對的鍵是一個包含字串 "date"
的字串物件, 而鍵值對的值則是一個包含字串 "2013.12.1"
的字串物件, 如圖 IMAGE_DB_AFTER_ADD_NEW_KEY 所示。
刪除鍵
刪除資料庫中的一個鍵, 實際上就是在鍵空間裡面刪除鍵所對應的鍵值對物件。
舉個例子, 如果鍵空間當前的狀態如圖 IMAGE_DB_EXAMPLE 所示, 那麼在執行以下命令之後:
redis> DEL book (integer) 1
鍵 book
以及它的值將從鍵空間中被刪除, 如圖 IMAGE_DB_AFTER_DEL 所示。
更新鍵
對一個數據庫鍵進行更新, 實際上就是對鍵空間裡面鍵所對應的值物件進行更新, 根據值物件的型別不同, 更新的具體方法也會有所不同。
舉個例子, 如果鍵空間當前的狀態如圖 IMAGE_DB_EXAMPLE 所示, 那麼在執行以下命令之後:
redis> SET message "blah blah" OK
鍵 message
的值物件將從之前包含 "hello world"
字串更新為包含 "blah blah"
字串, 如圖 IMAGE_DB_UPDATE_CAUSE_SET 所示。
再舉個例子, 如果我們繼續執行以下命令:
redis> HSET book page 320 (integer) 1
那麼鍵空間中 book
鍵的值物件(一個雜湊物件)將被更新, 新的鍵值對 page
和 320
會被新增到值物件裡面, 如圖 IMAGE_UPDATE_BY_HSET 所示。
對鍵取值
對一個數據庫鍵進行取值, 實際上就是在鍵空間中取出鍵所對應的值物件, 根據值物件的型別不同, 具體的取值方法也會有所不同。
舉個例子, 如果鍵空間當前的狀態如圖 IMAGE_DB_EXAMPLE 所示, 那麼當執行以下命令時:
redis> GET message "hello world"
GET 命令將首先在鍵空間中查詢鍵 message
, 找到鍵之後接著取得該鍵所對應的字串物件值, 之後再返回值物件所包含的字串 "helloworld"
, 取值過程如圖 IMAGE_FETCH_VALUE_VIA_GET 所示。
再舉一個例子, 當執行以下命令時:
redis> LRANGE alphabet 0 -1 1) "a" 2) "b" 3) "c"
LRANGE 命令將首先在鍵空間中查詢鍵 alphabet
, 找到鍵之後接著取得該鍵所對應的列表物件值, 之後再返回列表物件中包含的三個字串物件的值, 取值過程如圖 IMAGE_FETCH_VALUE_VIA_LRANGE 所示。