讓redis支持動態庫

jopen 8年前發布 | 9K 次閱讀 Redis NoSQL數據庫

原文  http://wendal.net/2013/10/20.html

 

So, let’s put some fun in redis

redis的命令列表是寫死在代碼里面,編譯后就沒法修改(跟nginx一個德行)

硬編碼一些額外的方法到redis中

最初寫的一個hello world級的測試命令

void wendalCommand(redisClient *c) {
    struct timeval tv;           // 從timeCommand拷貝的...
    addReplyMultiBulkLen(c,3);   // 共返回3個結果
    addReplyBulkCString(c, "Hi,Wendal"); // 輸出個字符串啦
    gettimeofday(&tv,NULL);              // 獲取時間, 也是從timeCommand拷貝的
    addReplyBulkLongLong(c,tv.tv_sec);   // 不解釋了
    addReplyBulkLongLong(c,tv.tv_usec);  // 不解釋了
}

然后在redisCommandTable中聲明一個新的命令,就搞定了

{"wendal", wendalCommand,1,"rR",0,NULL,0,0,0,0,0}

做得更靈活?上動態庫,哈哈

so,我聲明了2個新的命令, 加載/卸載動態庫

   {"loadlib",loadlibCommand,2,"wmaR",0,NULL,0,0,0,0,0},
    {"unloadlib",unloadlibCommand,2,"wmaR",0,NULL,0,0,0,0,0}

其中, 加載動態庫,就是接受一個路徑,并執行其redis_lib_init方法
// 簡化版的loadlibCommand
void loadlibCommand(redisClient *c) {
    void *handle;
    char *error;
    int (*redis_lib_init)(redisClient*, dict*);
    int re;

    handle = dlopen(c->argv[1]->ptr, RTLD_LAZY);
    if (!handle) {
        addReplyError(c, dlerror());
        return;
    }
    redis_lib_init = dlsym(handle, "redis_lib_init"); // 查找redis_lib_init
    if ((error = dlerror()) != NULL)  {
        dlclose(handle);
        addReplyError(c, error);
        return;
    }
    re = redis_lib_init(c, server.commands); // 執行之, 返回0就成功
    if (re) {
        dlclose(handle);
        addReplyError(c, "lib init error");
        return;
    }
    addReply(c,shared.ok);
    server.dirty ++;                        // 使dirty自增,這樣就能同步到slave了
}

redis動態庫示例

禁用flushdb命令

#include <redis.h>

static void* flushdb;

extern int redis_lib_init(redisClient *c) {
    flushdb = dictFetchValue(server.commands, sdsnew("FLUSHDB")); // 命令列表就是server.commands中,一個dict
    if (!flushdb) return 1; // 找不到? 被其他庫刪掉了?
    dictDeleteNoFree(server.commands, sdsnew("FLUSHDB")); // 刪除但不要執行free
    return 0;
}

extern void redis_lib_depose(redisClient *c) {
    dictAdd(server.commands, sdsnew("FLUSHDB"), flushdb); // 卸載的時候就賦值回去,呵呵
    return;
}

項目地址

https://raw.github.com/wendal/redis_plugins

https://raw.github.com/wendal/redis

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!