架構模式:MySQL 作為主存儲,Redis 作為緩存層。透過 UDF (User Defined Function) 封裝 Redis 客戶端操作,Trigger 捕獲資料異動自動呼叫 UDF,業務代碼無感知完成雙寫同步。
redis_hset(key, field, value) 寫入 Redis HashAFTER INSERT/UPDATE/DELETE ON table 呼叫 UDFyum install mysql-devel boost boost-devel -y
git clone https://github.com/mrpi/redis-cplusplus-client
// test.cpp
#include
#include "redisclient.h"
using namespace std;
static redis::client *g_client = NULL;
extern "C" char *redis_hset(UDF_INIT *initid, UDF_ARGS *args,
char *result, unsigned long *length,
char *is_null, char *error) {
try {
// 懶加載連線 (支援環境變數 REDIS_HOST)
if (!g_client) {
const char* c_host = getenv("REDIS_HOST");
string host = c_host ? c_host : "127.0.0.1";
g_client = new redis::client(host);
}
// 參數檢查
if (!(args->args && args->args[0] && args->args[1] && args->args[2])) {
*is_null = 1; return result;
}
// 呼叫 Redis HSET
if (g_client->hset(args->args[0], args->args[1], args->args[2])) {
return result; // 成功回傳空字串
} else {
*error = 1; return result;
}
} catch (const redis::redis_error& e) {
return result;
}
}
extern "C" my_bool redis_hset_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if (3 != args->arg_count) {
strncpy(message, "Usage: redis_hset('key', 'field', 'value')", MYSQL_ERRMSG_SIZE);
return -1;
}
// 強制字串型別
args->arg_type[0] = args->arg_type[1] = args->arg_type[2] = STRING_RESULT;
initid->ptr = NULL;
return 0;
}
g++ -shared -fPIC -I /usr/include/mysql \
-lboost_serialization -lboost_system -lboost_thread \
-o libmyredis.so anet.c test.cpp
cp libmyredis.so /usr/lib64/mysql/plugin/
chmod 777 /usr/lib64/mysql/plugin/libmyredis.so
CREATE FUNCTION redis_hset RETURNS STRING SONAME 'libmyredis.so';
DELIMITER $
CREATE TRIGGER tg_student_sync
AFTER INSERT ON Student
FOR EACH ROW
BEGIN
SET @id = (SELECT redis_hset(CONCAT('stu_', NEW.Sid), 'id', CAST(NEW.Sid AS CHAR(8))));
SET @name = (SELECT redis_hset(CONCAT('stu_', NEW.Sid), 'name', CAST(NEW.Sname AS CHAR(20))));
SET @age = (SELECT redis_hset(CONCAT('stu_', NEW.Sid), 'age', CAST(NEW.Sage AS CHAR)));
SET @gender = (SELECT redis_hset(CONCAT('stu_', NEW.Sid), 'gender', CAST(NEW.Sgen AS CHAR)));
SET @dept = (SELECT redis_hset(CONCAT('stu_', NEW.Sid), 'department', CAST(NEW.Sdept AS CHAR(10))));
END$
DELIMITER ;
mysql> INSERT INTO Student VALUES('09388165', 'Rose', 19, 'F', 'SS3-205');
Query OK, 1 row affected (0.27 sec)
redis-cli> HGETALL stu_09388165
1) "id" 2) "09388165"
3) "name" 4) "Rose"
5) "age" 6) "19"
7) "gender" 8) "F"
9) "department" 10) "SS3-205"
UPDATE/DELETE 觸發器同步修改/刪除