hiredis 判断主节点

前言

hiredis不支持哨兵模式,但是我们需要知道主节点的ip端口,不然无法正常写入,如果对redis很清晰的话,可以跳过下面的概念部分,本文基于原版hiredis做的。


集群模式

需要至少三个主节点才能开启,每个主节点分担n分支一的数据,也就是只要有主节点挂了,数据就丢失了(三个主节点就是每个节点承担三分之一的数据)

Redis集群_一只猪的思考的博客-CSDN博客_redis集群

主从模式

主节点能写能读,从节点只能读,缺点就是主节点挂了,尽管几个从节点重新选择了主节点,但是用户不知道最终选举的是哪个节点为主节点(解决办法就是哨兵模式)

redis主从设置_lt9700的博客-CSDN博客_redis主从

哨兵模式

哨兵的出现就是为了监视redis是否正常运转,一个哨兵监测一个redis节点,哨兵节点掌握了哪个是主节点的消息,用户直接跟哨兵通信,就知道哪个是主节点了。

每个哨兵都是独立的进程,有自己的监听端口,并且可以设置哨兵的独立密码(非redis登陆密码)。

但是哨兵如果挂了怎么办,所以用户通常一次会保存多个哨兵节点的ip以及端口,一个哨兵挂了,就问另外的哨兵,要是都挂了就没办法了。

可能有同学就要问了,那我直接保存所有redis节点不就行了,那还要哨兵干嘛,本文后面的代码就是基于这个思路写的。最大的缺点就是需要一个个尝试,我问哨兵一次我就知道哪个是主节点(不过从节点也会存储主节点的ip信息,理论上也能读取到主节点的信息),而且哨兵节点挂的几率比redis小的多,因为不承担业务。

Redis的哨兵模式_p&f°的博客-CSDN博客_redis哨兵模式

关于集群

hiredis并没有提供集群的库,不过有人基于hiredis做了集群的库

(下面的网址基于hiredis 1.0版本制作)

GitHub - Nordix/hiredis-cluster: C client library for Redis Cluster. This project is used and sponsored by Ericsson. It is a fork of the now unmaintained hiredis-vip.

(下面的网址集成了旧版本hiredis,下面这个hiredis-vip库不支持auth认证,也没有人维护了,不过有人提了合并代码请求关于认证的,可以看看)

https://github.com/vipshop/hiredis-vip

 集群跟主从没有必然联系,没开集群,也可以启用主从

hiredis-vip这个库可能会报错下面这个,说集群没开启

ERR This instance has cluster support disabled

应该是尝试了集群的命令,发现集群没开,redis的修改配置文件就可以开启集群了,如

解决:redis.clients.jedis.exceptions.JedisDataExceptionERR This instance has cluster support disabled_微风--轻许--的博客-CSDN博客

思路

先从配置文件读取当前所有的节点信息,配置文件如下,使用逗号分割ip地址

[redis]
redis-server = 192.168.174.190:6379,192.168.174.191:6380,192.168.174.192:6381

再挨个连过去,我们知道,使用role命令能知道自己是不是主节点,我们基于这个命令判断主节点(role命令返回的数组类型) (感兴趣的读者可以尝试另外一个思路,就是如果数组第二项是ip而非数字,那么第二项的ip必为主节点,反之当前节点为主节点)

# redis-cli -h 192.168.174.190 -p 6379
192.168.174.190:6379> auth 123456
OK
192.168.174.190:6379> role
1) "master"
2) (integer) 2868563
3) 1) 1) "192.168.174.191"
      2) "6380"
      3) "2868563"
   2) 1) "192.168.174.192"
      2) "6381"
      3) "2868563"
192.168.174.190:6379> exit
# redis-cli -h 192.168.174.191 -p 6380
192.168.174.191:6380> auth 123456
OK
192.168.174.191:6380> role
1) "slave"
2) "192.168.174.190"
3) (integer) 6379
4) "connected"
5) (integer) 2868619

代码

解析配置文件的头文件 (ini.h)

Parsing a .ini File in C

代码细节

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<hiredis/hiredis.h>
#include"ini.h"

typedef struct
{
    char* redis_server;
} configuration;

static int handler(void* config, const char* section, const char* name,
                   const char* value)
{
    configuration* pconfig = (configuration*)config;

    #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0

    if(MATCH("redis", "redis-server")){ 
        pconfig->redis_server = strdup(value);
    } else {
        return 1;
    }

    return 0;
}

int main()
{
    int res = 1;
    // 解析配置文件
    configuration config;
    char* path = "/home/redis-server.ini";
    if (ini_parse(path, handler, &config) < 0) {
        printf("Can't load %s\n", path);
        return 1;
    }

    // 寻找节点中的主节点
    char ip[32] = {0};
    int port = -1;
    char* redis_str = NULL;
    // 以逗号分割多个节点的ip端口,每次取出一个进行尝试连接
    // config.redis_server = "192.168.174.190:6379,192.168.174.191:6380,192.168.174.192:6381"
    redis_str = strtok(config.redis_server, ",");
    while (redis_str != NULL)
    {
        // 只支持ip,域名不确定能不能做
        sscanf(redis_str, "%[0-9.]:%d", ip, &port);

        if (check_master(ip, port) == 0){
            res = 0;
            break;
        }

        redis_str = strtok(NULL, ",");
    }

    // 打印结果
    if (res == 0) {
        printf("Find the master. ip %s, port %d\n", ip, port);
    } else {
        printf("Not find the master\n");
    }

    if (config.redis_server)
        free(config.redis_server);
    return;
}

int check_master(char *host, int port) 
{
    // 连接redis
    redisContext* context = redisConnect(host, port);
    if (context == NULL || context->err) {
        printf("Failed to initializing redis\n");
        return 1;
    }

    // 有密码认证要先密码认证
    redisCommand(context, "auth Admin_123");

    // 向redis的服务端发送 role
    redisReply* reply = redisCommand(context, "role");
    if (reply == NULL || context->err || reply->type != REDIS_REPLY_ARRAY) {
        const char *cause = context->err ? context->errstr : "(none)";
        printf("Failed to get redis status. %s\n", cause);
        if (reply)
            freeReplyObject(reply);
        redisFree(context);
        return 1;
    }

    // 判断返回里是否有 master,如果有则为主节点
    if (strstr(reply->element[0]->str, "master")){
        freeReplyObject(reply);
        redisFree(context);
        return 0;
    }

    freeReplyObject(reply);
    redisFree(context);
    return 1;
}

编译命令

gcc -o test.out test.c ini.c -lhiredis

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在LIN通信中,节点也可以进行诊断操作以监测和诊断整个LIN网络的状态和从节点的运行情况。以下是一些节点诊断的常见方法: 1. LIN网络初始化:节点在启动时会对LIN网络进行初始化和配置,并通过发送初始化帧来检测从节点的存在和状态。如果从节点未响应或响应异常,节点可以诊断问题所在并采取相应的措施。 2. 诊断命令发送:节点可以向从节点发送特定的诊断命令,以获取从节点的诊断信息或执行特定的诊断操作。这些命令可以包括请求故障码、读取参数、执行自检程序等。通过分析从节点的响应和返回的数据,节点可以判断节点的状态和健康状况。 3. 故障码读取:节点可以通过发送相应的诊断命令来请求从节点的故障码。从节点会将其存储的故障码发送给节点节点可以根据故障码来进行故障诊断和处理。 4. 状态监测:节点可以周期性地发送状态请求帧,要求从节点返回其当前的工作状态和健康状况。从节点通过回复状态帧来向节点报告其供电电压、温度、通信质量等信息。节点可以根据这些信息来判断节点是否存在故障或异常。 5. 通信质量监测:节点可以通过检测LIN通信的质量指标,如信号的响应时间、误码率等来判断通信线路的状态和可靠性。如果通信质量下降或超出预设阈值,节点可以诊断问题所在并采取相应的措施。 6. 故障处理:节点可以根据从节点的诊断信息和状态来采取相应的故障处理措施,如重启从节点、切换备份节点等。 通过以上节点诊断的方法,可以对LIN网络和从节点进行有效监测和诊断,及时发现和处理故障,提高整个系统的可靠性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值