我是如何通過新增一條命令學習redis原始碼的
準備工作
這篇文章不會告訴你啥是redis,如果不瞭解請自行搜尋學習。
我的操作環境是cent OS 6.5系統,vim編輯器。
我打算下載一個比較穩定的redis原始碼包進行修改測試。
$ wget http://download.redis.io/redis-stable.tar.gz
$ tar -zxvf redis-stable.tar.gz
$ cd redis-stable
進入redis-stable目錄可以看到src目錄,裡面是redis的實現原始碼,我下面的工作基本就是修改這裡面的內容。
我打算增加一條自定義的命令,並希望由此學習redis究竟是如何處理一條命令的。在此之前先看看redis自帶的命令是怎麼玩的。
[[email protected] bin]# redis-server /etc/redis/redis.conf
[[email protected] bin]# redis-cli
127.0.0.1:6379> set "pony" "大帥哥"
OK
127.0.0.1:6379> get "pony"
"大帥哥"
127.0.0.1:6379>
正式開始
我打算加入的命令叫STRUPPER,這條命令後面跟一個引數,也是key,返回key所對應的value的字母大寫轉換後的結果。比如key的值是”test”,那麼strupper key就返回”TEST”。
看起來似乎是一條沒有任何意義的命令(事實也是這樣,哈哈), 但是請明白我在意的不是命令本身,而是redis的命令處理機制。
在src/server.c中定義了redis的命令表,
struct redisCommand redisCommandTable[] = {
{"get",getCommand,2,"rF",0,NULL,1,1,1,0,0},
{"set",setCommand,-3,"wm",0,NULL,1,1,1,0,0},
{"setnx",setnxCommand,3,"wmF",0,NULL,1,1,1,0,0},
{"setex",setexCommand,4 ,"wm",0,NULL,1,1,1,0,0},
...
從程式碼中的註釋,我瞭解到如果要增加一條命令,應該首先在這個表中增加一行定義。並且我還了解到結構體的每個欄位的意義。
拿第一行舉例,”get”是命令的名字,getCommand是一個函式指標,型別是:
typedef void redisCommandProc(client *c);
2表示引數的數量,比如get命令的用法是get後面跟key,第一個引數是get本身,第二個引數是key。
“rF”是標識命令的屬性,r表示只讀,也就是這條命令不能修改key對應的value值。F表示這是條”快命令”,就是時間複雜度是O(1)或者O(log(N))。
緊接著的0暫時不用管,總是設定為0就行。
接下來的NULL域,大部分時候這個域都應該是NULL。少數時候可以放一個函式指標,用在命令後面引數比較多的時候,分不清哪個是key。
接下來的三個數字,對於get命令,第一個引數(key)在位置1上,最後一個引數(也是key)在位置1上,從第一個引數到最後一個引數的增量也是1。
最後兩個域總是初始化為0。
基於以上分析,我加了命令表底部加了一條命令:
{"strupper",strupperCommand,2,"w",0,NULL,1,1,1,0,0}
然後我需要在server.h中宣告下命令處理函式,
void strupperCommand(client *c);
函式的實現應該放在哪裡? redis是根據命令的型別來分類存放的,比如像getCommand和setCommand這樣的字串操作函式都是放在t_string.c檔案中實現的,strupper也算是字串處理函式,所以自然也是定義到這裡,我先定義一個空函式。
void strupperCommand(client *c)
{
}
到這裡,我先編譯下看看效果。
[[email protected] redis-stable]# make
[[email protected] redis-stable]# make install
[[email protected] bin]# redis-server /etc/redis/redis.conf
[[email protected] bin]# redis-cli
127.0.0.1:6379>
127.0.0.1:6379> set pony "test"
OK
127.0.0.1:6379> strupper
(error) ERR wrong number of arguments for 'strupper' command
127.0.0.1:6379> strupper pony
可以看出,當我執行strupper pony時卡住了,是因為函式是空的還沒實現。實現也是非常簡單,
void strupperCommand(client *c)
{
robj *o;
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL)
return;
if (o->type != OBJ_STRING) {
addReply(c,shared.wrongtypeerr);
return;
} else {
if (sdsEncodedObject(o))
{
sdstoupper(o->ptr);
}
addReplyBulk(c,o);
return;
}
}
大部分程式碼都是參考了get命令(因為這兩個命令實在是太像了),我只需把get取出來的value值轉換成大寫就行了,當然一些基本的檢查也是必須的。
lookupKeyReadOrReply函式根據傳入的key(c->argv[1])查詢,如果找到了會返回一個redis object物件,我們要的value就在這個物件裡。
addReply負責響應結果到客戶端。
sdsEncodedObject確保只對OBJ_ENCODING_RAW和OBJ_ENCODING_EMBSTR編碼的string物件進行操作,這樣才能用sdsXXX這樣的函式操作。
sdstoupper可以對字串整體進行大寫轉換。
重新編譯下,測試。
127.0.0.1:6379> set pony "test"
OK
127.0.0.1:6379>
127.0.0.1:6379> get pony
"test"
127.0.0.1:6379> strupper pony
"TEST"
結果跟預想的一樣。是個好的開始,後面再慢慢深入研究redis。
參考
相關推薦
我是如何通過新增一條命令學習redis原始碼的
準備工作 這篇文章不會告訴你啥是redis,如果不瞭解請自行搜尋學習。 我的操作環境是cent OS 6.5系統,vim編輯器。 我打算下載一個比較穩定的redis原始碼包進行修改測試。 $ wget http://download.redis.io
一條命令停止所有lxc容器,刪除所有lxc容器
gre troy 停止 des def code done awk don for i in $(virsh -c lxc:/// list | grep -v ‘Id‘ | awk ‘{print $2}‘);do virsh -c lxc:/// destroy $
每5秒向數據庫中插入一條記錄-學習筆記
每5秒向數據庫中插入一條記錄-學習筆記 import java.sql.SQLException; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import cn.itcast.web.dao.Syste
web每5秒向數據庫中插入一條記錄-學習筆記
每5秒向數據庫中插入一條記錄-學習筆記SystemListener import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import javax.servlet.ServletContextEvent; imp
一條命令解決mac版本python IDLE無法輸入中文問題
install 兩種 size tps 命令 輸入 homebrew NPU python3 安裝完Python通常自動就有了一個簡易的集成環境IDLE,但在mac上,無法在IDLE中使用中文。 通常故障有兩種情況: 在IDLE中,中文輸入法根本無法工作,不會彈出輸入框
一條命令深度清理你的mac
use DG 17. rep vid ash 通過 app pan 一條命令深度清理你的mac mac 用了一段時間後很快發現硬盤空間不夠了,就想找一些磁盤清理的工具,但是發現居然都是收費的. 就手工操作吧.方法其實非常簡單. 就一條命令, cd / du -hd 5 |
Linux如何讓一條命令快速修改用戶密碼?
div pre span display str echo one pan class 問題:修改密碼的命令為passwd,需要按Enter兩次,如何一條命令快速修改密碼呢? #實現命令: #echo 密碼 | passwd echo 密碼 | passwd --st
vue的資料來源-json格式陣列新增一條資料並重新整理。記錄一下
data () { return { arr: [{a:'111',b:'222',c:'333'},{a:'444',b:'555',c:'666'}], } }, method
Mac上一條命令搭建web伺服器
實際測試工作中偶爾會需要搭建Web伺服器環境,由於Mac OS X自帶了Apache和PHP環境,只需要簡單的啟動就可以。 開啟Apache 開啟Web伺服器的方法有兩種(預設啟動埠號是80): 開啟:系統偏好配置 ——> 共享 ——>Web共享 終端可以通過Apache啟動命令開
處理流程已辦完,選擇一個節點,新增一條待辦
---找到流程例項id--- select * from ACT_HI_PROCINST t where t.proc_inst_id_ in (select distinct t.proc_inst_id_ from ACT_HI_VARINST t where t.text_='402880e864
mybatis的Mapper中在mysql和oracl中新增一條記錄,返回記錄id
情景再現:專案中經常在mybatis的Mapper中在mysql和oracl中新增一條記錄後,需要返回記錄id: 1.使用mysql資料庫: //java的User物件,包含id,name,password三個屬性 <insert id="insert" useGenerate
新增一條新資料並返回此資料的ID(主鍵)
新增資料後返回Id <insert id="" parameterType="" useGeneratedKeys="true" keyProperty="id" keyColumn="id"> useGeneratedKeys:必須設定為true,否
ceph儲存 centos下通過Linux的ACL命令學習ACL許可權分配原理
注意:當然檔案和目錄的繼承又會有一些差異。因為檔案不像目錄,目錄的下層可再建立檔案和目錄,所以目錄在繼承上層目錄的ACL設定資訊時,會保證在它下層的目錄和檔案仍可以繼承它的ACL設定資訊。所以它要完全繼承上層目錄的ACL設定資訊。而檔案不需要繼承這些設定資訊。所以對於檔案來說僅會繼承scan使用者這條ACL設
Axure中繼器新增一條資料&刪除標記行
中繼器新增新增一條資料 1、新增一箇中繼器,並命名rep; 2、新增一個按鈕; 3、新增一個文字框,並命名txt。 4、點選按鈕設定互動。 5、雙擊“滑鼠單擊時”,進入“用例編輯對話方塊”, 選擇 “中繼器”->“資料集”->“新
Android7.0 Settings主選單新增一條item
往Android7.0的settings的主選單裡新增一條item. N與M的Settings不同,在M上只要找到Settings裡面的相應的佈局新增就好,但在N上由於Setting裡面的item不再受佈局控制,所以得在程式碼中新增. 找到/packages
新增一條新資料並返回此資料的ID
<insert id="" parameterType="" useGeneratedKeys="true" keyProperty="id" keyColumn="id"> useGeneratedKeys:必須設定為true,否則無法獲取到主鍵id。 keyPropert
mybatis 新增一條新資料並返回此資料的ID(主鍵)
通常資料庫中表的主鍵是‘自動遞增(mysql)’或’序列(oracle)‘,但插入資料後又要取得些條資料的ID(將ID做為主鍵) 利用Mybatis 的 selectKey來獲得: <!-- 新增部門 返回部門ID --> <insert id="ad
linux下安裝jdk 詳細步驟(一條命令即可安裝)
作為Java開發人員,在Linux下安裝一些開發工具是必備技能,本文以安裝jdk為例,詳細記錄了每一步的操作命令,以供參考。 第一種方法 只需要一條命令就可以安裝jdk: yum install java-1.8.0-openjdk* -y執行了這條命令不需要配
【轉】sqlplus中不能上下鍵選擇前一條命令解決方法
安裝一個叫rlwrap的工具: 已經上傳到本文附件:字尾為.rar,主要是51cto不支援.tar.gz字尾,實際上是一個tar.gz壓縮包 tar -zxvf rlwrap-0.30.tar.gz cd rlwrap-0.30 ./configure make
linux中一條命令修改使用者名稱的密碼
先要通過useradd新增使用者 useradd -d /opt/reconciliation -s /sbin/nologin -G root ftpUser 如果是普通的passwd,需要輸入兩次密碼: [[email protected] vsftpd]#