成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

向優秀代碼學習:Redis 代碼庫源碼概覽

開發 項目管理 前端 Redis
Redis是一個用ANSI C 編寫的開源數據結構服務器。“數據結構服務器”只是對靈巧的key-value存儲服務的另外一種稱謂。你不僅僅可以存儲簡單的字符串,還可以存儲包括 hash(或者map,甚至dicts),list,set,sorted set。

Redis是一個用ANSI C 編寫的開源數據結構服務器。“數據結構服務器”只是對靈巧的key-value存儲服務的另外一種稱謂。你不僅僅可以存儲簡單的字符串,還可以存儲包括 hash(或者map,甚至dicts),list,set,sorted set。我們在Top10 中 大量應用了Redis,大部分為了根據用戶搜索的日期和酒店的空房情況和價格建立索引。我發現Redis的代碼非常容易讀懂,甚至是對于像我這樣的新手。 代碼寫的很整潔,并且代碼量相對較小(4.5萬行左右),大部分都是單線程的,依賴也很少。所有的依賴都跟源代碼放在一起了,這中做法讓編譯它變得非常簡 單:clone它的庫,然后輸入make即可。

我決定通過為它增加一條命令來深入代碼。而這簡單的事情可以讓我知道Redis怎么處理一條命令并調度響應它。命令rand,接收一個整型值作為 max,并隨機返回0到max(不包含max)之間的一個整數。這不是使用鍵值存儲的思路,但是實現它將會很有啟發性。而我也肯定不會提交一個pull request。

免責聲明:如我之前所說,我絕對不是一個C語言的專家,因此這里所有的代碼和其解釋都符合這個條款。而且,我鏈接了Redis的一個不穩定分支,所以它是不穩定的。如果你自己去獲取Redis源碼,用你喜歡的編輯器來查看時,你將發現更多本文的不同,特別是如果你編譯并運行時會發現不同。

命令表在src/redis.c文件的靠頂部的位置。它是一個數組,數組的元素類型是redisCommand結構體。redisCommand是在src/redis.h中定義的。在redisCommandTable的上方有一塊比較詳細的注釋,對它的每一個field做了解釋。下面是get命令的定義:

  1. {"get",getCommand,2,"r",0,NULL,1,1,1,0,0}, 

***個field是命令的名字“get”。第二個field是一個函數指針,指向這個命令的具體實現(你可以查看實現細節t_string.c)。

第三個field是命令的參數數量限制(命令接收的參數個數)。指定這個,意味著在調用函數指針之前,查找和執行命令的代碼可以做一個預先驗證。這 種做法減少了在每個命令函數必須的錯誤處理代碼。參數的個數算上了命令名字本身,所以它只接受兩個參數:它自己的名字,key的名字(我們要獲取它的 值)。

第四個field,被設為”r”,用來指明這個命令是只讀的,不能修改這個key的value或狀態。有一大堆的字母標志,你都可以用在這個位置。 而且在附近的注釋塊中,每個字母標志都有詳細的解釋。緊跟這個field的field總是被設置為0,后面會用來計算。它只是第四個field的字符串包 含信息的位掩碼。

第六個field是NULL,因為它只有在你要用復雜的邏輯去告訴Redis哪個參數才是真正的key的時候才需要。一個key指向一個存儲在 Redis中的值的引用,對應簡單的參數,例如我們的max參數。這種機制,允許Redis在調用命令的實現之前,提取key的值(并且校驗key是否存 在)。如果這個field被設置了值,那么它將會是一個函數指針,指向的函數會返回一個參數索引的整型數組(db.c中 的zunionInterGetKeys是一個示例)。在get命令(其他大部分命令)的場景下,這個數組的信息傳達的信息跟后面三個field的一樣。 get命令只有一個參數,而它就是key。因此,***個參數(key)在位置1上,***一個參數(也是key)在位置1上,從***個參數到***一個參數的 增量也是1(譯者注:源碼注釋是:intkeystep;/* The step between first and last key */)。

redisCommand的***兩個field是命令的度量項,由Redis來設置,并且總是初始化為0。

在命令表的底部加上我們的命令:

  1. {"rand",randCommand,2,"rRl",0,NULL,0,0,0,0,0} 

命令的名字是“rand”,randCommand指向實現的指針(還未實現),它接收2個參數(命令名字和max)。至于標志,它是只讀的(r),返回隨機的,不確定的輸出(R),而且它可以在Redis還在加載數據的時候使用(l)。它沒有關鍵參數。

下一步是在src/redis.h中增加randCommand的函數原型。Redis命令的函數接收一個參數,一個redisClient的結構體,作為命令的參數同時也用來向實際的客戶端發送響應。

  1. void randCommand(redisClient *c); 

這個原型應該放在src/redis.h中與其他所有命令的原型一起。搜索下面的一行:

  1. /* Commands prototypes */ 

這將幫你找到正確的位置。

我們在src/redis.c中加一個空實現:

  1. void randCommand(redisClient *c) {  
  2.   

我將它加在了infoCommand定義的旁邊。現在,我們執行make命令。

  1. make 

然后,啟動我們剛剛編譯成共的Redis服務(如果你已經有一個Redis服務在本地運行,你應該停掉它):

  1. > src/redis-server 

接著我們在另外的終端中運行Redis客戶端,并試著運行我們的命令:

  1. >redis-cli 

首先,我們試一試我們的異常處理:

  1. redis 127.0.0.1:6379> rand  
  2. (error) ERR wrong number of arguments for 'rand' command 

很好,參數數量限制檢查是正常的。這一次我們指定一個參數:

  1. redis 127.0.0.1:6379> rand 1 

Redis卡住了。這正是我預期的,因為我在randCommand函數中沒有任何響應。將服務停掉,我們接著回去看代碼。

我們想返回一個整數,因此我在代碼里翻找例子,***在src/t_zset.c中找到了zcardCommand。這個命令用addReplyLongLong來向客戶端返回一個64位(long long)的整數。我們也試一下:
  1. void randCommand(redisClient *c) {  
  2.     addReplyLongLong(c,3);  

然后,我們在make一次,并測試命令:

  1. redis 127.0.0.1:6379> rand 1  
  2. (integer) 3  
  3.   
  4. redis 127.0.0.1:6379> rand 2  
  5. (integer) 3  
  6.   
  7. redis 127.0.0.1:6379> rand 3  
  8. (integer) 3 

好吧,結果不是太隨機,但這只是個開始。我們從命令里獲取參數max,并返回一個由max限制的隨機數:

  1. void randCommand(redisClient *c) {  
  2.     long max;  
  3.   
  4.     if (getLongFromObjectOrReply(c,c->argv[1],&max,NULL) != REDIS_OK)  
  5.         return;  
  6.   
  7.     addReplyLongLong(c,random() % max);  

盡管Redis在整個代碼庫中都用原始類型和C型字符串,但它同時也擁有自己的以更通用的方式存在的內部對象系統,用來表示字符串,長整 型和更復雜的類型。一個利用這種類型的例子就是:每個命令的參數。每一個命令的參數都作為一個Redis對象被存在redisClient實例c的 field,數組argv里。(譯注:在源碼src/redis.c里面redisClient是一個結構體,argv是一個redisObject指針 的指針)。在src/t_string.c里面有一個從Redis對象獲取長整型的例子:getrangeCommand,它調用了src/object.c中的getLongFromObjectOrReply函數。

 getLongFromObjectOrReply函數接收一個redisClient實例作參數,并檢查它的第二個參數是否是一個長整型, 如果是則將第二個參數的指針賦給第三個參數(這個參數是一個指針類型),并且返回REDIS_OK。如果第二個參數不是長整型(或溢出了),函數返回 REDIS_ERR。這個方法的美麗之處在于:如果我們從我們的randCommand函數得到的返回值是REDIS_ERR,所有必須的錯誤響應已經被 發送給客戶端了。我們再試一下我們的命令:

  1. redis 127.0.0.1:6379> rand 10  
  2. (integer) 9  
  3. redis 127.0.0.1:6379> rand notanumber  
  4. (error) ERR value is not an integer or out of range  
  5. redis 127.0.0.1:6379> rand 10  
  6. (integer) 3  
  7. redis 127.0.0.1:6379> rand 10  
  8. (integer) 1  
  9. redis 127.0.0.1:6379> rand 100  
  10. (integer) 43  
  11. redis 127.0.0.1:6379> rand 100  
  12. (integer) 55  
  13. redis 127.0.0.1:6379> rand 100  
  14. (integer) 86 

看起來不錯!rand看起來是一個沒有多少意義的命令,但是從實現它的過程中學到很多關于Redis的東西,我希望你跟著做下來也同樣學到很多。請在評論 里告訴我這篇文章里是否明顯的錯誤。我也很高興知道這篇文章對你很有用或者你很喜歡它。我考慮寫一些類似的東西,關于Redis或者其他的開源的代碼庫。

原文鏈接:http://www.heychinaski.com/blog/2013/10/14/a-look-at-the-redis-source-code

譯文鏈接:http://blog.jobbole.com/50837/

責任編輯:陳四芳 來源: 伯樂在線
相關推薦

2023-05-04 23:59:46

React開發工具

2023-11-26 18:03:00

代碼C++

2020-05-25 11:14:59

代碼程序開發

2020-03-09 14:10:48

代碼開發工具

2020-10-23 09:07:17

開源代碼開發

2020-04-12 21:44:47

網絡架構工具網絡配置

2012-06-27 14:04:22

folly

2014-09-28 10:26:06

OpenJDK

2015-07-01 15:08:56

OpenStack開源社區代碼貢獻

2017-10-22 16:16:03

程序員編程代碼

2014-09-12 10:38:01

程序員代碼

2014-07-29 13:55:10

程序員代碼

2021-05-26 08:50:37

JavaScript代碼重構函數

2022-10-09 18:39:46

分層代碼復用

2017-06-07 14:58:39

Redis源碼學習Redis事務

2022-02-14 09:12:00

無代碼低代碼開發工具

2022-06-06 12:02:23

代碼注釋語言

2023-10-10 10:57:12

JavaScript代碼優化

2011-08-08 15:05:50

iPhone 網站

2011-11-03 17:02:00

微軟Samba代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91国内精品久久 | www.国产.com| 亚洲成人高清 | 天天精品综合 | 国产高清精品一区二区三区 | 日韩av一区二区在线观看 | 日本不卡免费新一二三区 | 久久不卡 | 欧美性猛片aaaaaaa做受 | 超碰97av | 国产精品中文字幕在线观看 | 国产九九精品 | 久久99精品久久久久久狂牛 | 亚洲一一在线 | 成人福利网站 | 久久精品91 | 日本精品一区二区三区视频 | 一级午夜aaa免费看三区 | 欧美日韩中文字幕 | 一区二区三区四区在线免费观看 | 北条麻妃99精品青青久久主播 | 亚洲一二三区在线观看 | 亚洲美女视频 | 久草免费视| 黄网站免费在线 | 国产四区 | 欧美aaa一级片 | 欧美色偷拍 | 日韩一区二区在线免费观看 | 在线欧美视频 | 欧美日韩国产精品一区 | 国产传媒在线播放 | 欧美日韩亚洲视频 | 欧美久久视频 | 91久久久久久久久久久久久 | 国产一区二区不卡 | 久久精品亚洲精品国产欧美 | 欧美成人一区二免费视频软件 | 一道本不卡 | 伊人影院99 | 精精精精xxxx免费视频 |