Redis module development, Redis triggers RocketMQ Client to publish messages

Redis has a pubsub function. I feel that it is inconvenient to use and fails to meet my requirements. So I plan to develop a third-party module for Redis. When the key times out, it will automatically notify RocketMQ of the timeout key. RocketMQ consumers are consuming messages and responding. Business logic processing.

 

The first thing to do is to download RocketMQ's C++ client source code on github:

https://github.com/apache/rocketmq-client-cpp

Then compile, the compilation is generally smooth, and an error is encountered:

libboost_iostreams.a for lack of <pbin.v2/libs/iostreams/build/gcc-4.8.5/release/link-static/runtime

Just install the bzip2 package: yum install bzip2-devel

 

The next step is to develop Redis modules.

The module is also very simple, I just posted the code directly:

 


#define REDISMODULE_EXPERIMENTAL_API
#include "../../redismodule.h"

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <unistd.h>
#include <memory.h>

#include "CProducer.h"
#include "CCommon.h"
#include "CMessage.h"
#include "CSendResult.h"



static CProducer *producer = NULL;
static char* MQAddr  = NULL;
static char* MQTopic = NULL;
static char* MQTag   = NULL;


static int SendTOMQ (RedisModuleCtx *ctx, const char* expirekey)
{
    CMessage *msg = CreateMessage(MQTopic);
    SetMessageTags(msg, MQTag);
    SetMessageKeys(msg, expirekey);

    CSendResult result;

    SetMessageBody(msg,  "Redis Key Timeout\n");
    SendMessageSync(producer, msg, &result);
    if (result.sendStatus == E_SEND_OK) {
        printf ("Notify MQ successn: %s\n", expirekey);
        return REDISMODULE_OK;
    }
    
    else {
        printf ("Notify MQ fail: %s\n", expirekey);
        return  RedisModule_ReplyWithError(ctx,"Send to MQ fail\n");
    }

}


//int (*RedisModuleNotificationFunc)(RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key);
extern "C" int KeyExpireEventCallback (RedisModuleCtx *ctx, int type, const char *event, RedisModuleString *key)
{
    REDISMODULE_NOT_USED(type);
    REDISMODULE_NOT_USED(event);

    size_t  keylen = 0;
    const char *expireKey = RedisModule_StringPtrLen(key, &keylen);

    printf ("RocketmqMoudle callback exe: %s\n", expireKey);

    //const char* topic = "FOREGROUND_CONSUMER";//
    //const char* tag   = "EXPIRE";//
    if (MQAddr == NULL || MQTopic == NULL || MQTag == NULL) {
        return  RedisModule_ReplyWithError(ctx,"You haven't set the parameters of MQ yet.");
    }

    return SendTOMQ(ctx, expireKey);

    
}




extern "C" int PublishKey(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
    if (argc != 2) 
        return RedisModule_WrongArity(ctx);

    const char *expirekey = RedisModule_StringPtrLen(argv[1], NULL);
    

    return SendTOMQ (ctx, expirekey);

}

/*
write readonly admin deny-oom deny-script allow-loading pubsub random allow-stale no-monitor fast getkeys-api no-cluster
*/
extern "C" int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) 
{
    if (RedisModule_Init(ctx,"rocketmq",1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) 
		return REDISMODULE_ERR;

    size_t len;
    /* Log the list of parameters passing loading the module. */
    for (int j = 0; j < argc; j++) {
        const char *s = RedisModule_StringPtrLen(argv[j], &len);
        printf("Module loaded with ARGV[%d] = %s\n", j, s);
    }

    if (argc != 3) {
        return RedisModule_WrongArity(ctx);
    }

    
    MQAddr  = strdup(RedisModule_StringPtrLen(argv[0], &len));
    MQTopic = strdup(RedisModule_StringPtrLen(argv[1], &len));
    MQTag   = strdup(RedisModule_StringPtrLen(argv[2], &len));


    if (RedisModule_CreateCommand(ctx,"rocketmq.pubfun", PublishKey,"readonly",1,1,1) == REDISMODULE_ERR)
        return REDISMODULE_ERR;
 

    RedisModule_SubscribeToKeyspaceEvents (ctx, REDISMODULE_NOTIFY_EXPIRED, KeyExpireEventCallback);
    producer = CreateProducer("redis_producer");
    SetProducerNameServerAddress(producer, MQAddr);
    if (StartProducer(producer)) {
        printf("Module loaded StartProducer fail\n");
        return REDISMODULE_ERR;
    }
        

    return REDISMODULE_OK;
}



# Compile flags for linux / osx

SHOBJ_CFLAGS ?= -W -Wall -fno-common -g -ggdb -std=c99 -O2
SHOBJ_LDFLAGS ?= -shared

M_R_FLAGS  = -Wall -Wno-deprecated -fPIC -fno-strict-aliasing -O3 -DNDEBUG 
M_D_FLAGS  = -Wno-deprecated -fPIC -fno-strict-aliasing -O0 -DDEBUG  
M_INCLUDES = -I/root/rocketmq-client-cpp-master/bin/include -I/root/rocketmq-client-cpp-master/bin/include/jsoncpp -I/root/rocketmq-client-cpp-master/include 
LIBPATH    = -L/root/rocketmq-client-cpp-master/bin
LDFLAGS   =  -lrocketmq


.SUFFIXES: .c .so .xo .o

all: rocketmq.so

.cpp.xo:
	$(CC) -I. $(CFLAGS) $(SHOBJ_CFLAGS) $(M_D_FLAGS) $(M_INCLUDES) $(LIBPATH) -fPIC -c $< -o $@

rocketmq.xo: ../../redismodule.h

rocketmq.so: rocketmq.xo
	$(LD) -o $@ $< $(SHOBJ_LDFLAGS) $(LDFLAGS) $(LIBS) -lc

clean:
	rm -rf *.xo *.so

Small things to pay attention to in module development: The first function executed in the RedisModule_OnLoad function must be RedisModule_Init, otherwise it will report segmentfalt

The next step is to configure the redis.conf configuration file

Add a line:

loadmodule /opt/redis-unstable/src/modules/rocketmq.so your RocketMQ IP and port your TOPIC your TAG

Modify a line:

notify-keyspace-events Ex
 

You can also develop Kafka notification messages, MQTT notification messages, or use a third-party module to do spike business logic or distributed lock-related business logic.

Guess you like

Origin blog.csdn.net/langeldep/article/details/85692948