歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋(píng)果6袋
6
麥子學(xué)院

Redis學(xué)習(xí)之外部擴(kuò)展模塊詳解

發(fā)布時(shí)間:2017-08-22 22:03  回復(fù):0  查看:2928   最后回復(fù):2017-08-22 22:03  
Redis從4.0版本開(kāi)始加入了對(duì)外部擴(kuò)展模塊的支持。外部擴(kuò)展模塊可以實(shí)現(xiàn)新的Redis命令,新的Redis數(shù)據(jù)結(jié)構(gòu),總之基本上可以做到所有Redis內(nèi)核可以做的事情。本文和大家分享的就是redis外部擴(kuò)展模塊相關(guān)內(nèi)容,一起來(lái)看看吧,希望對(duì)待學(xué)習(xí)redis有所幫助。
  我個(gè)人認(rèn)為這是迄今為止,Redis最重要的一個(gè)改進(jìn)。友好的API、完善的文檔和健壯的基礎(chǔ)結(jié)構(gòu),會(huì)快速吸引大量的第三方開(kāi)發(fā)者不斷貢獻(xiàn)新的內(nèi)容,Redis的用途必然會(huì)更加廣泛,用戶群也會(huì)隨之?dāng)U大。
  模塊的實(shí)現(xiàn)
  Redis模塊需要引入 redismodule.h ,用C、C++或其他提供C binding的開(kāi)發(fā)語(yǔ)言實(shí)現(xiàn),并編譯成動(dòng)態(tài)庫(kù) .so 文件。基于 redismodule.h 提供的API實(shí)現(xiàn)的模塊,在API不變的情況下(API版本號(hào)相同),可以兼容不同Redis版本而不需要重新編譯。
  在開(kāi)發(fā)模塊的時(shí)候并不需要依賴Redis的源代碼或開(kāi)發(fā)庫(kù),只需要把 redismodule.h 拷貝到工程下邊引用,實(shí)現(xiàn)并導(dǎo)出方法 RedisModule_OnLoad 即可。
  模塊可以做什么
  訪問(wèn)Redis數(shù)據(jù)空間
  Redis提供了兩套數(shù)據(jù)訪問(wèn)的API,一套是較高層的,類(lèi)似于Lua腳本的API,往往用來(lái)調(diào)用API沒(méi)有提供支持的Redis命令。另一套是底層API,速度很快,基本和Redis原生命令一樣快,也提供了一些對(duì)各種數(shù)據(jù)結(jié)構(gòu)的進(jìn)行處理的函數(shù),是推薦的數(shù)據(jù)訪問(wèn)方式。
  高層API使用 RedisModule_Call 調(diào)用Redis命令,如:
  RedisModuleCallReply *reply;reply = RedisModule_Call(ctx,"INCR","sc",argv[1],"10");
  底層API使用 RedisModule_OpenKey 打開(kāi)并獲取Key指針繼而進(jìn)行后續(xù)處理,如:
  RedisModuleKey *key;key = RedisModule_OpenKey(ctx,"somekey",REDISMODULE_READ);
  實(shí)現(xiàn)新的數(shù)據(jù)結(jié)構(gòu)
  對(duì)于簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),可以使用DMA(direct memory access)將結(jié)構(gòu)編碼保存到Redis的String類(lèi)型中,如:
  // 獲取字符串內(nèi)存指針繼而修改其內(nèi)容
  size_t len;
  char *myptr = RedisModule_StringDMA(key,&len,REDISMODULE_WRITE);
  // 增大,減少或創(chuàng)建字符串
  RedisModule_StringTruncate(key,1024);
  也可以使用API注冊(cè)并實(shí)現(xiàn)新的數(shù)據(jù)結(jié)構(gòu),可以控制內(nèi)存的分配與釋放,RDB序列化,AOF重寫(xiě)等。 這里 是Redis官方的一個(gè)例子,好奇的同學(xué)可以自己點(diǎn)進(jìn)去看看。
  實(shí)現(xiàn)阻塞命令
  阻塞命令(Blocking commands)會(huì)阻塞客戶端,直到某個(gè)期望的事件發(fā)生才會(huì)返回,比如List的 BLPOP 命令。模塊API也提供了實(shí)現(xiàn)阻塞命令的功能,在寫(xiě)這篇文章的時(shí)候,Blocking Command的相關(guān)API還處于試驗(yàn)階段,其設(shè)計(jì)還沒(méi)有最終確定,所以這里就不詳細(xì)說(shuō)明了,以后再將這部分補(bǔ)全。
  加載模塊
  模塊有兩種加載方式,一是在配置文件 redis.conf 中使用 loadmodule /path/to/mymodule.so在Redis啟動(dòng)時(shí)加載。另一種方式在運(yùn)行時(shí)使用命令 MODULE LOAD /path/to/mymodule.so 加載。加載的模塊可以使用命令 MODULE LIST 查看,使用 MODULE UNLOAD mymodule 卸載。
  在載入的模塊的時(shí)候可以傳入?yún)?shù),如: loadmodule mymodule.so foo bar 1234 ,參數(shù)會(huì)被傳入模塊的 OnLoad 方法中。
  對(duì)Redis Cluster的支持
  模塊是可以支持Redis Cluster的,但是目前還找不到相關(guān)的介紹,只是在官方文檔里提到兩個(gè)相關(guān)的API函數(shù): RedisModule_IsKeysPositionRequest(ctx) 與 RedisModule_KeyAtPos(ctx,pos)。于是仔細(xì)的看了一下官方API文檔中的相關(guān)部分,并對(duì)照了一下其他模塊的實(shí)現(xiàn),猜了一下大概的實(shí)現(xiàn)方式。
  首先,在創(chuàng)建Redis模塊的命令時(shí),需要調(diào)用API方法:
  int RedisModule_CreateCommand(RedisModuleCtx *ctx,const char*name, RedisModuleCmdFunc cmdfunc,const char*strflags,intfirstkey,intlastkey,intkeystep);
  其中的 strflags 參數(shù)的一個(gè)flag為 getkeys-api ,意思是這個(gè)方法是否支持返回參數(shù)中key。一個(gè)方法接收的參數(shù)有多個(gè),但并不是每一個(gè)都是key,比如 LRANGE key start stop 中,只有第一個(gè)參數(shù)是key。而Redis需要知道一個(gè)命令涉及到哪些key,才能在集群中找到對(duì)應(yīng)的服務(wù)器并執(zhí)行命令。
  如果一個(gè)命令支持 getkeys-api ,那么在集群環(huán)境下, RedisModule_IsKeysPositionRequest(ctx) 方法就會(huì)返回true,就是說(shuō)需要方法標(biāo)出參數(shù)中的key,這就用到了 RedisModule_KeyAtPos(ctx,pos) 方法,其中 pos 是參數(shù)的位置。下邊是 rxzsets 中相關(guān)的代碼:
  int ZUnionTopKCommand(RedisModuleCtx *ctx, RedisModuleString **argv,intargc){
  ...
  if (RedisModule_IsKeysPositionRequest(ctx)) {
  for (int i = 0; i < numkeys; i++) {
  RedisModule_KeyAtPos(ctx, 3 + i);
  }
  return REDISMODULE_OK;
  }
  ...
  }
  int RedisModule_OnLoad(RedisModuleCtx *ctx){
  ...
  if (RedisModule_CreateCommand(ctx, "zuniontop", ZUnionTopKCommand,
  "readonly getkeys-api", 1, 1,
  1) == REDISMODULE_ERR)
  ...
  }
  Redis Module Hub
  Redis Module Hub 是Redis官方的模塊倉(cāng)庫(kù),目前已經(jīng)有將近二十個(gè)模塊,其中一大半是Redis Labs自己貢獻(xiàn)的,算是拋磚引玉吧,下邊隨便拿出幾個(gè)做一下簡(jiǎn)單的介紹:
  · 對(duì)現(xiàn)有數(shù)據(jù)結(jié)構(gòu)功能的擴(kuò)展,如:
  · rxkeys 提供了按正則表達(dá)式批量獲取與刪除條目的功能
  · rxhashes 提供了在Hash中改變現(xiàn)有條目的值并返回原值的原子操做
  · rxlists 提供了7個(gè)新的列表操作方法。
  · 新數(shù)據(jù)結(jié)構(gòu),如:
  · rejson 提供了對(duì)原生JSON格式支持,允許對(duì)JSON數(shù)據(jù)內(nèi)的值進(jìn)行獲取與修改
  · Redis Graph 添加了對(duì)圖數(shù)據(jù)庫(kù)的支持
  · redisearch 實(shí)現(xiàn)了全文搜索,使用特殊的壓縮數(shù)據(jù)結(jié)構(gòu),加快了搜索的速度,并且減少了內(nèi)存占用
  · redis-ml 實(shí)現(xiàn)了多個(gè)機(jī)器學(xué)習(xí)常用的數(shù)據(jù)結(jié)構(gòu)及相關(guān)方法
  · 對(duì)功能的擴(kuò)展,如:
  · graphicsmagick 提供類(lèi)似GraphicsMagick的圖片處理功能,從此生成縮略圖,打水印都可以在Redis里做了
  · redablooms 基于RedisString的Bloom filter,可以用于ID生成
  · password 提供加密的密碼存儲(chǔ)


來(lái)源:千里
您還未登錄,請(qǐng)先登錄

熱門(mén)帖子

最新帖子

?