使用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!');