Redis-Sentinel(哨兵模式),看这篇就够了哦

2023-11-19

简介

Sentinel(哨兵) 是redis的高可用性解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进行下线时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。然后由新的主服务器代替已下线的主服务器继续处理命令请求。

例如下图所示:

在这里插入图片描述

当Server1 掉线后:

在这里插入图片描述

升级Server2 为新的主服务器:

在这里插入图片描述

启动并初始化Sentinel

启动一个Sentinel可以使用命令:

redis-sentinel /path/to/your/sentinel.conf

或者:redis-server /path/to/your/sentinel.conf --sentinel
这两个命令执行的效果是一样的。

当一个Sentinel启动时它需要经历如下步骤:

  • 初始化Sentinel服务器
  • 替换普通Redis代码为Sentinel的专用代码
  • 初始化Sentinel状态
  • 根据用户给定的Sentinel配置文件,初始化Sentinel监视的主服务器列表
  • 创建连接主服务器的网络连接

初始化Sentinel服务器

因为sentinel执行的工作和普通redis服务器执行的工作不同,所以sentinel的初始化过程和普通redis服务器的初始化过程并不完全相同,Sentinel并不需要读取RDB/AOF文件来还原数据状态。
在这里插入图片描述

替换普通Redis代码为Sentinel的专用代码

端口:sentinel.c/REDIS_SENTINEL_PORT:26379

命令表:sentinel.c/sentinelcmds

启动 Sentinel 的第二个步骤就是将一部分普通 Redis 服务器使用的代码替换成 Sentinel 专用代码。

比如说, 普通 Redis 服务器使用 redis.h/REDIS_SERVERPORT 常量的值作为服务器端口:

#define REDIS_SERVERPORT 6379

而 Sentinel 则使用 sentinel.c/REDIS_SENTINEL_PORT 常量的值作为服务器端口:

#define REDIS_SENTINEL_PORT 26379

普通 Redis 服务器使用 redis.c/redisCommandTable 作为服务器的命令表:

struct redisCommand redisCommandTable[] = {
    {"get",getCommand,2,"r",0,NULL,1,1,1,0,0},
    {"set",setCommand,-3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
    {"setnx",setnxCommand,3,"wm",0,noPreloadGetKeys,1,1,1,0,0},
    // ...
    {"script",scriptCommand,-2,"ras",0,NULL,0,0,0,0,0},
    {"time",timeCommand,1,"rR",0,NULL,0,0,0,0,0},
    {"bitop",bitopCommand,-4,"wm",0,NULL,2,-1,1,0,0},
    {"bitcount",bitcountCommand,-2,"r",0,NULL,1,1,1,0,0}

而 Sentinel 则使用 sentinel.c/sentinelcmds 作为服务器的命令表, 并且其中的 INFO 命令会使用 Sentinel 模式下的专用实现 sentinel.c/sentinelInfoCommand 函数, 而不是普通 Redis 服务器使用的实现 redis.c/infoCommand 函数:

struct redisCommand sentinelcmds[] = {
    {"ping",pingCommand,1,"",0,NULL,0,0,0,0,0},
    {"sentinel",sentinelCommand,-2,"",0,NULL,0,0,0,0,0},
    {"subscribe",subscribeCommand,-2,"",0,NULL,0,0,0,0,0},
    {"unsubscribe",unsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},
    {"psubscribe",psubscribeCommand,-2,"",0,NULL,0,0,0,0,0},
    {"punsubscribe",punsubscribeCommand,-1,"",0,NULL,0,0,0,0,0},
    {"info",sentinelInfoCommand,-1,"",0,NULL,0,0,0,0,0}
};

Sentinel用于较少的Redis命令,大部分命令在Sentinel客户端都不支持,并且Sentinel拥有一些特殊的功能,这些需要Sentinel在启动时将Redis服务器使用的代码替换为Sentinel的专用代码。在此期间Sentinel会载入与普通Redis服务器不同的命令表。
Sentinel不支持SET、DBSIZE等命令;保留支持PING、PSUBSCRIBE、SUBSCRIBE、UNSUBSCRIBE、INFO等指令;这些指令在Sentinel工作中提供了保障。

初始化 Sentinel 状态

在应用了 Sentinel 的专用代码之后, 接下来, 服务器会初始化一个 sentinel.c/sentinelState 结构(后面简称“Sentinel 状态”), 这个结构保存了服务器中所有和 Sentinel 功能有关的状态。

struct sentinelState{
    // 当前纪元,用于实现故障转移
    uint64_t current_epoch;
    // 保存了所有被这个sentinel监视的主服务器
    // 字典的键是主服务器的名字
    // 字典的值是一个指向sentinelRedisInstance和结构的指针
    dict *masters;
    // 是否进入了 TILT 模式?
    int tilt;
    // 目前正在执行时的脚本的数量
    int running_scripts;
    // 进入tilt模式的时间
    mstime_t tilt_start_time;
    // 最后一次执行时间处理器的时间
    mstime_t previous_time;
    // 一个fifo队列,包含了所有需要执行的用户脚本
    list *scripts_queue;
}sentinel;

初始化Sentinel监视的主服务器列表

Sentinel状态中的masters字典记录了所有被sentinel监视的主服务器的相关信息,其中:

  • 字典的键是被监视主服务器的名字
  • 而字典的值则是被监视主服务器对应的 sentinel.c/sentinelRedisInstance 结构

每个sentinelRedisInstance结构(后面简称“实例结构”)代表一个被Sentinel监视的服务器实例,这个实例可以是主服务器,从服务器,或者是另外一个sentinel。

实例结构属性包含:

typedef struct sentinelRedisInstance {

    // 标识值,记录了实例的类型,以及该实例的当前状态
    int flags;

    // 实例的名字
    // 主服务器的名字由用户在配置文件中设置
    // 从服务器以及 Sentinel 的名字由 Sentinel 自动设置
    // 格式为 ip:port ,例如 "127.0.0.1:26379"
    char *name;

    // 实例的运行 ID
    char *runid;

    // 配置纪元,用于实现故障转移
    uint64_t config_epoch;

    // 实例的地址
    sentinelAddr *addr;

    // SENTINEL down-after-milliseconds 选项设定的值
    // 实例无响应多少毫秒之后才会被判断为主观下线(subjectively down)
    mstime_t down_after_period;

    // SENTINEL monitor <master-name> <IP> <port> <quorum> 选项中的 quorum 参数
    // 判断这个实例为客观下线(objectively down)所需的支持投票数量
    int quorum;

    // SENTINEL parallel-syncs <master-name> <number> 选项的值
    // 在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量
    int parallel_syncs;

    // SENTINEL failover-timeout <master-name> <ms> 选项的值
    // 刷新故障迁移状态的最大时限
    mstime_t failover_timeout;

    // ...

} sentinelRedisInstance;

sentinelRedisInstance.addr属性是一个指向sentinelAddr结构的指针,这个结构保存着实例的IP地址和端口号

typedef struct sentinelAddr {

    char *ip;

    int port;

} sentinelAddr;

对Sentinel状态的初始化将引发对masters字典的初始化,而masters字典的初始化是根据被载入的Sentinel配置文件来进行的。

如果用户在启动 Sentinel 时, 指定了包含以下内容的配置文件:


#####################
# redis-master1 configure #
#####################

sentinel monitor redis-master1 127.0.0.1 6379 2

sentinel down-after-milliseconds redis-master1 30000

sentinel parallel-syncs redis-master1 1

sentinel failover-timeout redis-master1 900000

#####################
# redis-master2 configure #
#####################

sentinel monitor redis-master2 127.0.0.1 12345 5

sentinel down-after-milliseconds redis-master2 50000

sentinel parallel-syncs redis-master2 5

sentinel failover-timeout redis-master2 450000

那么 Sentinel 将为主服务器 redis-master1 创建如下图所示的实例结构:

在这里插入图片描述
并且为主服务器 redis-master2 创建如下图所示的实例结构:

在这里插入图片描述
这两个实例结构又会被保存到 Sentinel 状态的 masters 字典中, 如下图所示:

在这里插入图片描述

创建连向主服务器的网络连接

当实例结构初始化完成之后,Sentinel将会开始创建连接Master的网络连接,这一步Sentinel将成为Master的客户端。
Sentinel和Master之间会创建一个命令连接和一个订阅连接:

  • 一个是命令连接, 这个连接专门用于向主服务器发送命令, 并接收命令回复
  • 一个是订阅连接,订阅连接用于Sentinel之间进行信息广播,每个Sentinel和自己监视的主从服务器之间会订阅sentinel:hello频道(注意Sentinel之间不会创建订阅连接,它们通过订阅sentinel:hello频道来获取其他Sentinel的初始信息)

这里需要说一下为什么需要两个连接?

在 Redis 目前的发布与订阅功能中, 被发送的信息都不会保存在 Redis 服务器里面, 如果在信息发送时, 想要接收信息的客户端不在线或者断线, 那么这个客户端就会丢失这条信息。

因此, 为了不丢失 sentinel:hello 频道的任何信息, Sentinel 必须专门用一个订阅连接来接收该频道的信息。

而另一方面, 除了订阅频道之外, Sentinel 还又必须向主服务器发送命令, 以此来与主服务器进行通讯, 所以 Sentinel 还必须向主服务器创建命令连接。

并且因为 Sentinel 需要与多个实例创建多个网络连接, 所以 Sentinel 使用的是异步连接。

当Sentinel服务器初始化完成之后,会每10s向已经连接的被监视的服务器发送INFO命令,主服务器会返回自身的信息,以及它下面的从服务器的信息。

Sentinel也会去主动连接从服务器

在这里插入图片描述

获取主服务器信息

sentinel默认会每10秒一次,给主服务器发送info命令,并且通过分析info命令,来判断当前主服务器的信息。

通过分析info命令,sentinel会得到两方面的信息:一是主服务器的运行ID以及其role域记录的服务器角色,二是关于主服务器属下所有从服务器的信息,由slave字符串开头,每行IP记录一个IP地址、端口号、offset(用于与主服务器aof)、lag(延迟时间)等。

因此,sentinel无序建立和从服务器的连接,也可以知道从服务器的情况。sentinel只需要将info获得的返回结果,分析并更新到sentinel的sentinelState结构体的相应属性即可。

另外,sentinel在更新结构体时,还会分析每一个从服务器是否存在,如果是现有的则更新结构体,如果不是现有的则新增一个结构体。
在这里插入图片描述
从上述可知,主从服务器sentinelRedisInstance的主要区别,一是flags属性主是SRI_MASTER而从是SRI_SLAVE;二是名称主服务器是sentinel起的,从服务器是IP:端口号;三是主服务器有个slaves属性,指向一个字典,该字典键是从服务器的IP:端口号,值是表示从服务器的sentinelRedisInstance。

获取从服务器信息

当sentinel发现有新的从服务器,除了会为其创建实例结构,还会与其建立连接,连接也是包括订阅连接和命令连接。且默认下,每十秒也会给从服务器发送info命令。

在这里插入图片描述
根据info命令,可以提取出以下主要信息:运行ID、角色、主服务器ip与端口、主从连接状态、从服务器优先级、从服务器偏移量

向主服务器和从服务器发送信息

在默认情况下, Sentinel会以每两秒一次的频率,通过命令连接向所有被监视的主服务器和从服务器发送以下格式的命令:

publish _sentinel_:hello "<s_ip>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"

这条命令向服务器的_sentinel_:hello频道发送了一条信息,信息的内容由多个参数组成:

其中,以s_开头的参数记录的是Sentinel本身的信息,而m_开头的参数记录的则是主服务器的信息。
在这里插入图片描述

接收来自主从服务器频道的信息

接收信息

当Sentinel与一个主服务器或者从服务器建立起订阅连接之后,Sentinel就会通过订阅连接,向服务器发送以下命令:subscribe sentinel:hello,Sentinel对_sentinel_:hello频道的订阅会一直持续到Sentinel与服务器的连接断开为止。

在这里插入图片描述
此时实例结构信息如下图所示:

在这里插入图片描述

当Sentinel从_sentinel_:hello频道接收到信息时,Sentinel会对这条信息进行分析,提取出信息中的 Sentinel IP地址,Sentinel 端口号,Sentinel 运行ID等八个参数,并进行以下检查:

  • 如果获取到的 runid 与 Sentinel 自己的 runid 相同,那么说明这条信息是 Sentinel 自己发送的,Sentinel 将丢弃这条信息,不做进一步处理
  • 如果信息中记录的 runid 和接收信息的 Sentinel 的 runid 不相同,那么说明这条信息是监视同一个服务器的其他Sentinel 发来的,接收信息的 Sentinel 将根据信息中的各个参数,对相应主服务器的实例结构进行更新

更新sentinels字典

Sentinel 为主服务器创建的实例结构中的 snetinels 字典保存了除 Sentinel 本身之外,所有同样监视这个主服务器的其他 Sentinel 信息,字典的键是sentinel的ip:port,值是对应的sentinel实例。

当一个 sentinel 接受到其他 sentinel 发来的信息时,目标 sentinel 会从信息中提取出以下两方面的参数:

  • 与sentinel有关的参数:sentinel 的ip地址,端口号,运行id和配置纪元
  • 与主服务器有关的参数:sentinel 正在监视的主服务器的名字,ip地址,端口号和配置纪元

根据信息中提取出的主服务器参数,目标sentinel会在自己的 sentinel 状态的 masters 字典中查找相应的主服务器实例结构,然后根据提取出的 sentinel 参数,检查主服务器实例结构的 sentinels 字典中,sentinel 的实例结构是否存在:

  • 如果 sentinel 的实例结构已经存在,那么对源 sentinel 的实例结构进行更新
  • 如果 sentinel 的实例结构不存在,说明 sentinel 是刚刚开始监视主服务器的新 sentinel。目标 sentinel 会为sentinel 创建一个新的实例结构,并将这个结构添加到 sentins 字典里面

创建连向其他sentinel的连接

当sentinel通过频道信息发现一个新的sentinel时,它不仅会为新sentinel在sentinels字典中创建相应的实例结构,还会创建一个连向新sentinel的命令连接,而新sentinel也同样会创建连向这个sentinel的命令连接,最终监视同一主服务器的多个sentinel将形成相互连接的网络。

在这里插入图片描述

检测Master是否主观下线

默认情况下,Sentinel 每隔1秒钟,向sentinelRedisInstance 实例中的所有 Master、Slave、Sentinel 发送 PING 命令,通过其他服务器的回复来判断其是否仍然在线。

sentinel down-after-milliseconds redis-master 50000

在Sentinel 的配置文件中,down-after-nilliseconds 选项指定了 sentinel 判断实例进入主观下线所需的时间长度,实例在 down-after-milliseconds 毫秒内,连续向 sentinel 返回无效回复,那么 sentinel 会修改这个实例所对应的实例结构,在结构的 flags 属性中打开 sri_s_down 标识,以此来表示这个实例已经进入主观下线状态。

在这里插入图片描述

down-after-nilliseconds选项需要注意的是:

对于监视同一个主服务器的多个Sentinel来说,这些 Sentinel 所设置的 down-after-nilliseconds 选项的值也可能不同,因此,当一个 Sentinel 将主服务器判断为主观下线时,其他 Sentinel 可能仍然认为主服务器处于在线的状态,比如:
Sentinel1 的配置:

sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 50000

而 Sentinel2 的配置:

sentinel monitor master 127.0.0.1 6379 2
sentinel down-after-milliseconds master 10000

那么当 master 的断线时长超过 10000 毫秒之后,Sentinel2 会将 master 判断为主观下线,而Sentinel1 认为 master 仍然在线。只有当 master 的断线时长超过 50000 毫秒之后,Sentinel1 和Sentinel2 才会都认为 master 进入了主观下线状态。

检测Master是否客观下线

当前Sentinel认为其下线只能处于主观下线状态,要想判断当前Master是否客观下线,还需要询问其他Sentinel,并且所有认为Master主观下线或者客观下线的总和需要达到quorum配置的值,当前Sentinel才会将Master标志为客观下线。

在这里插入图片描述
当前Sentinel向sentinelRedisInstance实例中的其他Sentinel发送如下命令:

sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid>

命令询问其他sentinel是否同意主服务器已下线,如下图参数:

在这里插入图片描述

接收到命令的 Sentinel,会根据命令中的参数检查主服务器是否下线,检查完成后会返回如下图参数:

在这里插入图片描述
接收命令中的回复

根据其他 sentinel 发回的命令回复,sentinel 将统计其他 sentinel 同意主服务器已下线的数量,当这一数量达到配置指定的判断客观下线所需的数量时,sentinel 会将主服务器实例结构 flags 属性的 SRI_O_DOWN 标识打开,表示主服务器已经进入客观下线状态。

客观下线状态的判断条件::

当认为主服务器已经进入下线状态的 Sentinel 的数量,超过 Sentinel 配置中设置的 quorum 参数的值,那么该Sentinel就会认为主服务器已经进入客观下线状态。比如说,如果 Sentinel 在启动时载入了以下配置:sentinel monitor master 127.0.0.1 6379 2,那么包括当前 Sentinel 在内,只要总共有两个 Sentinel 认为主服务器已经进入下线状态,那么当前 Sentinel 就将主服务器判断为客观下线。
又比如说,如果 Sentinel 在启动时载入了以下配置:sentinel monitor master 127.0.0.1 6379 5
那么包括当前 Sentinel 在内,总共要有五个 Sentinel 都认为主服务器已经下线,当前 Sentinel 才会将主服务器判断为客观下线。

选举领头sentinel

当一个主服务器被判断为客户下线后,监视这个下线主服务器的各个sentinel 会进行协商,选举出一个领头sentinel,并由领头 sentinel 对下线主服务器进行故障转移操作:

以下是选举领头 sentinel 的规则和方法

  • 所有在线的 Sentinel 都有被选为领头 Sentinel 的资格,换句话说,监视同一个主服务器的 多个在线 Sentinel 中的任意一个都有可能成为领头Sentinel
  • 每次进行领头 Sentinel 选举之后,不论选举是否成功,所有 Sentinel 的配置纪元 (configuration epoch)的值都会自增一次。 配置纪元实际上就是一个计数器,并没有什么特 别的。
  • 在一个配置纪元里面, 所有 Sentinel 都有一次将某个 Sentinel 设置为局部领头 Sentinel 的机会 并且局部领头一旦设置,在这个配置每个发现主服务器进入客观下线的 Sentinel 都会要求其他 Sentinel 将自己设置为局部领头Sentinel。
  • 当一个 Sentinel(源Sentinel)向另一个 Sentinel(目标Sentinel)发送 SENTINEL ismaster-down-by-addr 命令,并且命令中的 runid 参数不是*符号而是源 Sentinel 的 runid 时,这表示源 Sentinel 要求目标 Sentinel 将前者设置为后者的局部领头 Sentinel
  • Sentinel 设置局部领头 Sentinel 的规则是先到先得:最先向目标 Sentinel 发送设置要求的源 Sentinel 将成为目标 Sentinel 的局部领头 Sentinel ,而之后接收到的所有设置要求都会被目标 Sentinel 拒绝
  • 目标 Sentinel 在接收到 SENTINEL is-master-down-by-addr 命令之后,将向源 Sentinel 返回 一条命令回复,回复中的 leader_runid 参数和 leader_epoch 参数分别记录了目标 Sentinel 的局部领头 Sentinel 的 runid 和配置纪元
  • 源 Sentinel 在接收到目标 Sentinel 返回的命令回复之后,会检查回复中 leader_epoch 参数 的值和自己的配置纪元是否相同,如果相同的话,那么源 Sentinel 继续取出回复中的 leader_runid 参数, 如果 leader_runid 参数的值和源 Sentinel 的 runid 一致,那么表示目标 Sentinel 将源 Sentinel 设置成了局部领头 Sentinel
  • 如果有某个 Sentinel 被半数以上的 Sentinel 设置成了局部领头 Sentinel,那么这个 Sentinel 成为领头 Sentinel。举个例子,在一个由 10 个 Sentinel 组成的 Sentinel 系统里面,只要有大于等于 10/2+1=6 个 Sentinel 将某个Sentinel 设置为局部领头 Sentinel,那么被设置的那个 Sentinel 就会成 为领头 Sentine
  • 因为领头 Sentinel 的产生需要半数以上 Sentinel 的支持,并且每个 Sentinel 在每个配置纪元里面只能设置一次局部领头 Sentinel,所以在一个配置纪元里面,只会出现一个领头 Sentinel
  • 如果在给定时限内,没有一个Sentinel 被选举为领头 Sentinel ,那么各个 Sentinel 将在一段时间之后再次进行选举,直到选出领头 Sentinel 为止

故障转移

选出的领头 Sentinel 开始执行故障转移,操作分为三个步骤:

  • 在已下线的主服务器的从服务器中选中一个从服务器,并将其转换为主服务器
  • 让已下线的主服务器属下的从服务器改为复制新的主服务器
  • 如果已下线的主服务器回复了的话,让其作为新的主服务器的从服务器

选出新的主服务器

故障转移操作第一步要做的就是在已下线主服务器属下的所有从服务器中,挑选出一个状态良好,数据完整的从服务器,然后向这个从服务器发送 slaveof no one 命令,将这个从服务器转换为主服务器。

新的主服务器是怎么挑选出来的?

领头Sentinel会将已下线主服务器的所有从服务器保存到一个列表里面,然后按照以下规则,一项一项地对列表进行过滤:

  • 删除列表中所有处于下线或者断线状态的从服务器,这可以保证列表中剩余的从服务器都是正常在线的。
  • 删除列表中所有最近五秒内没有回复过领头 Sentinel 的 INFO 命令的从服务器,这可以保证列表中剩余的从服务器都是最近成功进行过通信的。
  • 删除所有与已下线主服务器连接断开超过 down-after-milliseconds * 10毫秒的从服务器: down-after-milliseconds 选项指定了判断主服务器下线所需的时间,而删除断开时长超过down-after-milliseconds * 10毫秒的从服务器,则可以保证列表中剩余的从服务器都没有过早地与主服务器断开连接,换句话说,列表中剩余的从服务器保存的数据都是比较新的。
  • 之后,领头 Sentinel 将根据从服务器的优先级,对列表中剩余的从服务器进行排序,并选出其中优先级最高的从服务器。
  • 如果有多个具有相同最高优先级的从服务器,那么领头Sentinel 将按照从服务器的复制偏移量,对具有相同最高优先级的所有从服务器进行排序,并选出其中偏移量最大的从服务器(复制偏移量最大的从服务器就是保存着最新数据的从服务器)。
  • 最后,如果有多个优先级最高、复制偏移量最大的从服务器,那么领头 Sentinel 将按照 runid 对这些从服务器进行排序,并选出其中 runid 最小的从服务器。

修改从服务器的复制目标

通过向从服务器发送 slaveof 命令来实现

将旧的主服务器变为从服务器

当旧的主服务器上线之后,向他发送 slaveof 命令

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis-Sentinel(哨兵模式),看这篇就够了哦 的相关文章

  • 使用 sidekiq 处理两个独立的 Redis 实例?

    下午好 我有两个独立但相关的应用程序 他们都应该有自己的后台队列 阅读 单独的 Sidekiq 和 Redis 进程 然而 我希望偶尔能够将工作推给app2的队列来自app1 从简单的队列 推送的角度来看 如果app1没有现有的 Sidek
  • Redis部署配置-主从复制

    目前我有两台服务器 我已经部署了基于node js Express JS的Web服务API 我正在使用 Redis 来缓存 JSON 字符串 将此设置部署到生产中的最佳选择是什么 我懂了here https stackoverflow co
  • 如何从 python 将无穷大传递给 redis?

    我正在使用 redis py 并希望将 inf 和 inf 与 ZRANGEBYSCORE 一起使用 我尝试使用 inf 的字符串和浮点来执行此操作 但它们返回一个空集 我怎样才能做到这一点 EDIT 我尝试执行以下命令 redis Str
  • Node.js 上通过套接字连接 Redis

    由于共享托管 目标主机上的我的 redis 服务器不在端口上运行 而是在非常特定的套接字上运行 可以通过套接字文件连接到该套接字 只有我的用户可以访问 但是 我还没有找到如何通过套接字指定连接node redis and connect r
  • 保护节点 Redis

    我正在尝试保护 Node Redis IPC 服务器以使用私钥 公钥 我已经关注了本教程 http bencane com 2014 02 18 sending redis traffic through an ssl tunnel wit
  • 如何统计 Redis 流中未读或已确认的消息?

    使用 Redis 5 0 3 假设我们创建一个名为streamy和一个消费群体consumers XGROUP CREATE streamy consumers MKSTREAM 然后向其中添加一些消息 XADD streamy messa
  • 库存管理系统的 SQL 与 NoSQL

    我正在开发一个基于 JAVA 的网络应用程序 主要目的是拥有在多个称为渠道的网站上销售的产品的库存 我们将担任所有这些渠道的管理者 我们需要的是 用于管理每个渠道的库存更新的队列 库存表 其中包含每个通道上分配的正确快照 将会话 ID 和其
  • Redis hash写入速度非常慢

    我面临一个非常奇怪的问题 使用 Redis 时 我的写入速度非常糟糕 在理想的情况下 写入速度应该接近 RAM 上的写入速度 这是我的基准 package redisbenchmark import redis clients jedis
  • Redis 排序集和解决关系

    我正在使用 Redis 排序集来存储我正在处理的项目的排名 我们没有预料到 我们想要如何处理关系 Redis 按字典顺序对具有相同分数的条目进行排序 但我们想要做的是对具有相同分数的所有条目给予相同的排名 例如在以下情况 redis 127
  • Redis INCRBY 有限制

    我想知道是否有一种方法可以通过我的应用程序的单次往返在 Redis 中执行此操作 对于给定的键K 其可能值V是范围内的任意整数 A B 基本上 它有上限和下限 When an INCRBY or DECRBY发出命令 例如INCRBY ke
  • 从redis中检索大数据集

    一台服务器上的应用程序查询另一台服务器上运行的 Redis 查询的结果数据集约为 250kzrangebyscore objects locations inf inf这在应用程序服务器上似乎需要 40 秒 当使用命令执行时redis cl
  • 如何将 ActionController::Live 与 Resque + Redis 一起使用(用于聊天应用程序)

    我正在尝试为我的 Rails 应用程序构建聊天功能 我在用ActionController Live Puma Resque Redis为了这 所以基本上在这种情况下 redissubscribe方法正在后台运行 使用resque 到目前为
  • 通过 StackExchange.Redis 连接到 Redis Servier

    我尝试使用以下方法制作一个测试项目Redis https redis io服务器 通过 Virtual Box 安装在 Linux Ubuntu 虚拟机上 Linux 机器通过 Virtual Box 的桥接适配器与本地网络连接 Virtu
  • 如何测试我的 Redis 缓存是否正常工作?

    我已经安装了 django redis cache 和 redis py 我遵循了 Django 的缓存文档 据我所知 以下设置就是我所需要的 但我如何判断它是否正常工作 设置 py CACHES default BACKEND redis
  • SignalR 无法连接到 SSL 上的 Azure Redis

    我目前在 Azure 上托管我的 redis 缓存服务器 并让 signalR 依赖它作为骨干 使用以下内容 GlobalHost DependencyResolver UseRedis 服务器 端口 密码 eventKey 这可以在端口
  • Spring Data JPA Redis:无法编写基于自定义方法的查询

    我已经使用 Redis 配置了 Spring Data JPA 并使用RedisRepositorieswith 提供了类似的方法find findAll 所有这些方法似乎都工作得很好 但我无法编写我的自定义方法 RedisEntity f
  • redis - 使用哈希

    我正在使用 redis 为我的 Web 应用程序实现社交流和通知系统 我是 redis 的新手 我对哈希值及其效率有一些疑问 我读过这篇很棒的文章Instagram 帖子 http instagram engineering tumblr
  • StackExchange.Redis的正确使用方法

    这个想法是使用更少的连接和更好的性能 连接会随时过期吗 对于另一个问题 redis GetDatabase 打开新连接 private static ConnectionMultiplexer redis private static ID
  • 想要在后台不间断地运行redis-server

    我已经下载了 redis 2 6 16 tar gz 文件并安装成功 安装后我运行 src redis server 它工作正常 但我不想每次都手动运行 src redis server 而是希望 redis server 作为后台进程持续
  • 如何在Redis中只保存一个数据库?

    我是 Redis 新手 有一个与备份相关的问题 目前 我有一个实例在 Windows 服务器上运行 在这个实例中 我当前有一项 工作 将数据存储在一个数据库中 我不想备份这些数据 我必须创造一份新工作 我的第一个想法是将数据存储在另一个数据

随机推荐

  • 当矩阵的秩小于未知数的个数时,方程组有无数个解;当矩阵的秩等于未知数的个数时,方程组只有零解。...

    当矩阵的秩小于未知数的个数时 方程组有无数个解 当矩阵的秩等于未知数的个数时 方程组只有零解 转载于 https www cnblogs com 2019 02 11 p 10586212 html
  • springboot配置启动后自动打开浏览器访问项目

    springboot配置项目启动后自动打开浏览器访问项目 有时候在单机部署 或者项目没有在IDea 开发工具中运行 idea可以自动打开tomcat项目 需要项目启动后自动打开浏览器访问项目 配置方法很简单 一 具体步骤 所用到的代码只有下
  • QT在图片中间绘制文字,获取文字size 和 pos

    QFont ft this gt font 获取系统当前字体对象 ft setPixelSize 15 设置字体大小 QFontMetrics fm QFontMetrics ft 创建字体计算类 double pixW fm width
  • 【基础】Flink -- ProcessFunction

    Flink ProcessFunction 处理函数概述 处理函数 基本处理函数 ProcessFunction 按键分区处理函数 KeyedProcessFunction 定时器与定时服务 基于处理时间的分区处理函数 基于事件时间的分区处
  • 用vscode创建一个c项目_vscode怎样编写c程序

    一 获取C C 扩展 1 打开vscode 2 ctrl shift x打开商店 3 搜索C C 安装 重启vscode 二 安装GCC 1 下载MinGW 2 打开安装程序 安装到D盘 需要创建MinGW文件夹 安装完成之后生成MinGW
  • (手工)【sqli-labs32-38】宽字节注入、报错回显、字符/数字型注入

    目录 一 推荐 二 手工 SQL注入基本步骤 三 Less32 GET Bypass custom filter adding slashes to dangerous chars 3 1 简介 宽字节注入 报错回显 字符型注入 3 2 第
  • JVM简介说明

    转自 JVM简介说明 下文笔者讲述JVM的简介说明 如下所示 JVM简介 JVM的功能是Java应用程序的运行环境 它是Java虚拟机 JVM用于运行java的字节码文件 JVM可以将字节码转换为硬件 操作系统指令 JVM用于同操作系统内层
  • 【HJ31】 单词倒排

    题目描述 对字符串中的所有单词进行倒排 说明 1 构成单词的字符只有26个大写或小写英文字母 2 非构成单词的字符均视为单词间隔符 3 要求倒排后的单词间隔符以一个空格表示 如果原字符串中相邻单词间有多个间隔符时 倒排转换后也只允许出现一个
  • ubuntu 串口助手通信收发数据不一致

    文章目录 问题背景 一 解决方案 1 直接更换硬件 靠这个解决的 2 其他参考 总结 问题背景 主机1 win10笔记本电脑 主机2 ubuntu16 04的宸曜工控机 主机3 ubuntu14 04的一个小盒子 串口助手 cutecom
  • pmd java规则_静态代码扫描 (一)——PMD 自定义规则入门

    阅读该文章前 最好已经对 PMD 有了初步的认识和了解 可参考静态分析工具 PMD 使用说明 准备工作 首先在PMD 官网下载最新版本的文件 目前最新版本是 5 4 1 下载 pmd bin 5 4 1 zip 和 pmd src 5 4
  • QT串口助手的实现

    serial c include serial h include ui serial h serial serial QWidget parent QWidget parent ui new Ui serial ui gt setupUi
  • 【数据库】MySQL三大日志:binlog、redo log和undo log

    MySQL三大日志 binlog redo log和undo log 日志是mysql数据库的重要组成部分 记录着数据库运行期间各种状态信息 mysql日志主要包括错误日志 查询日志 慢查询日志 事务日志 二进制日志几大类 作为开发 我们重
  • 土壤含水量仪的监测方法

    土壤含水量监测仪对土壤内部水分含量情况进行监测 可实现对灾害隐患点土壤含水量的长期实时监测 仪器主机采用低功耗设计 工作功耗可达毫瓦级 根据滑坡隐患点的特点 仪器主机采用多通道设计 可根据实际情况接驳1 4路土壤含水量传感器对监测点不同深度
  • Python安全攻防之第二章Python语言基础

    2 3 Python模块的安装与使用 python模块的安装 pip3 install 模块名称 py 3 m pip install 模块名称 python模块的导入与使用 1 Import模块名称 采用 Import模块名称 方式时 需
  • Shell中的算术运算

    let expr bc都是在Bash shell环境中进行数学运算时我们会用到的工具 一 整数运算 let 当使用let时 变量名之前不能再添加 用法 var1 2 var2 3 let result var1 var2 echo resu
  • 一文搞懂积分不等式证明(积分证明题总结笔记3/3)

    积分证明题是考研中难度较大的板块 很多学弟学妹们希望我出一篇总结文章 故作本文 希望对大家有所帮助 本文所涉及题目 均是来自市面上常见题册 李林880 张宇1000题 汤家凤1800等 由于内容较多 故分为三部分 等式证明 点击进入 由积分
  • Qt 绘图设备,QPixmap 和QImage 相互转化

    Qt的绘图系统允许使用相同的API在屏幕和其他打印设备上进行绘制 整个绘图系统基于 QPainter QPainterDevice 和 QPaintEngine三个类 QPainter用来执行绘制的操作 QPaintDevice是一个二维空
  • ospf和mgre的综合应用

    1 R6为ISP只能配置IP地址 R1 R5的环回为私有网段 首先划分好IP地址 如下图所示 然后对各个环回和接口进行IP配置 如下面所示 对r1 r1 int l0 r1 LoopBack0 ip add 192 168 1 1 24 r
  • Mybatis-plus查看完整执行sql

    Mybatis plus查看完整执行sql application properties 文件 mybatis plus configuration log impl org apache ibatis logging stdout Std
  • Redis-Sentinel(哨兵模式),看这篇就够了哦

    文章目录 简介 启动并初始化Sentinel 初始化Sentinel服务器 替换普通Redis代码为Sentinel的专用代码 初始化 Sentinel 状态 初始化Sentinel监视的主服务器列表 创建连向主服务器的网络连接 获取主服务