MySQL觸發器調用udf同步redis的發佈訂閱模式

使用C/C++擴展Hiredis和Redis交互

Hiredis

Hiredis is a minimalistic C client library for the Redis database.

https://github.com/redis/hiredis

進入 Hiredis 目錄:
在這裏插入圖片描述

make

在這裏插入圖片描述在這裏插入圖片描述

make install

如果MySQL是docker環境,將hiredis的安裝包docker cp到容器中後,執行如下命令:

mkdir -p /usr/local/include/hiredis /usr/local/include/hiredis/adapters /usr/local/lib
cp -pPR hiredis.h async.h read.h sds.h /usr/local/include/hiredis
cp -pPR adapters/*.h /usr/local/include/hiredis/adapters
cp -pPR libhiredis.so /usr/local/lib/libhiredis.so.0.14
cd /usr/local/lib && ln -sf libhiredis.so.0.14 libhiredis.so
cp -pPR libhiredis.a /usr/local/lib
mkdir -p /usr/local/lib/pkgconfig
cp -pPR hiredis.pc /usr/local/lib/pkgconfig

編譯UDF函數

A user-defined function (UDF) is a way to extend MySQL with a new function that works like a native (built-in) MySQL function such as ABS() or CONCAT().

For the UDF mechanism to work, functions must be written in C or C++ (or another language that can use C calling conventions), your operating system must support dynamic loading and you must have compiled mysqld dynamically (not statically).

創建redis.cpp

#include <stdio.h>
#include <string.h>
#include <string>
#include <mysql.h>
#include <hiredis/hiredis.h>
using namespace std;

const char *redisHost="173.0.20.109";
int redisPort=16379;
const char *redis_password="redis-secret-0123passw0rd";

extern "C" long long redis_publish(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)  
{  

    redisContext* c = redisConnect(redisHost, redisPort); 
    char *channelName = (char *)args->args[0];  
    char *message = (char *)args->args[1]; 
    if ( c->err)  
    {  
        redisFree(c);  
        strcpy(error,"connect error");  
        return -1;
    }
   
    redisReply* r = (redisReply *)redisCommand(c, "AUTH %s", redis_password);
    if (r->type == REDIS_REPLY_ERROR) {
    	return -1;
    }
    r = (redisReply*)redisCommand(c, " publish %s %s ",channelName,message);
    if (r->type == REDIS_REPLY_ERROR) {
    	return -1;
    }
    freeReplyObject(r);

    redisFree(c);  //free redis connect
    return 1;
}  

extern "C" my_bool redis_publish_init(UDF_INIT *initid, UDF_ARGS *args, char *message)  
{  
    if(args->arg_count!=2){
        strcpy(
            message
        ,   "Expected exactly two arguments"
        );      
        return 1;
    }
    return 0;
} 

編譯

g++ -fPIC -Wall -shared -DMYSQL_DYNAMIC_PLUGIN -o redis.so redis.cpp -I /usr/include/mysql/ -L /usr/local/lib/ -l hiredis

生成.so文件
在這裏插入圖片描述

mysql> show variables like 'plugin_dir';
docker cp redis.so 容器ID:/usr/lib/mysql/plugin

用sql操作redis

運行.so文件

查看MySQL中已經存在的UDF函數

select * from mysql.func;

在這裏插入圖片描述
創建redis_publish函數

CREATE FUNCTION redis_publish RETURNS STRING SONAME 'redis.so';

在這裏插入圖片描述

錯誤

errno: 11 libhiredis.so.0.14: cannot open shared object file: No such file or directory

sudo cp /usr/local/lib/libhiredis.so.0.14 /usr/lib/

ERROR 1127 (HY000): Can’t find symbol ‘redis_publish’ in library
在這裏插入圖片描述
這是因爲MySQL中已經存在的UDF函數包括了redis.so,重新編譯生成的redis.so替換源文件後,需要把mysql中原有的redis.so的UDF函數都DROP掉,然後重新導入。
在這裏插入圖片描述

運行

mysql> select redis_publish('msg_channel','hello world!');

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章