Redis系列(七)Redis主从、哨兵、cluster集群方案解析

2023-11-19

Redis主从

为什么要有主从?

  1. 故障恢复:主挂了或数据丢失了,从库有数据备。
  2. 负载均衡,流量分发。比如主写从读,减小单实例的读写压力。
  3. 高可用,sentinel和cluster都是基于主从实现的。

主从数据同步

一般而言,主数据库负责写,从数据库负责读。

主从数据同步分为两部分:同步和命令传播

同步

slave向master发送psync命令,请求数据同步。psync有两种模式:完整重同步(全量同步)、部分重同步(增量同步)

建立连接

  1. 假设有个节点A,当它第一次成为主节点的一个从节点时,会执行replicaof ip port命令。此时:从节点会保存主节点的IP与端口等信息,主节点也会保存从节点的信息,保证两节点正常连接。

完整重同步(全量同步)

  1. 建立连接后,从节点A向master发送数据同步指令(psync),指令中A向master发送自己保存的master_replid、offset等字段。

  2. master收到数据同步指令后,比较其中的master_repid和自己的repid是不是一样。如果不一样或者传的空值,那么就需要全量同步。

    • 备注:4.0之前,用的是runId,但是runId每次实例重启时都会改变,会导致主从切换;或者重启的时候,都需要全量同步,所以4.0之后采用
      replid
  3. slave首次连接master,slave肯定是没有master的replid,触发全量同步。

  4. 全量同步过程:

    1. master开始执行bgsave,生成一个rdb文件,并且把rdb文件传输给我们的slave,同时把master的replid以及offerset(master的数据偏移量,处理完命令后,都会写入自身的offerset)。

    2. slave接收到rdb文件后,清空slave自己内存中的数据,然后用rdb来加载数据,这样保证了slave拿到的数据是master生成rdb时候的最新数据。

    3. 由于master生成rdb文件是用的bgsave生成,所以,在生成文件的时候,master是可以接收新的指令的。这些新的指令需要找一个地方保存,等到slave加载完rdb文件以后要同步给slave。

      • 在master生成rdb文件期间,接收新的指令会保存在一个内存区间,这个内存区间就是replication_buffer(缓冲区)。我们可以通过以下方式设置replication_buffer的大小。
      client-output-buffer-limit replica 256mb 64mb 60
      //256mb:硬性限制,如果接收的新指令超过256M,master断开和slave的连接,再次连接得重新全量同步。
      //64mb 60:软限制,如果接收的新指令超过64M并且持续时间超过了60s还没进行同步(slave没加载完rdb文件),则master断开和slave的连接。
      
      • 所以replication_buffer空间不能太小,如果太小,为了数据安全,会关闭跟从库的网络连接。再次连接得重新全量同步,但是问题还在,会导致无限的同步的问题。
    4. 等到slave加载完rdb文件后,master把replication_buffer中的数据、对应的offset同步给slave。slave执行完这些写命令后,此时的数据库状态便和master一致了。

触发条件

1. slave第一次接入master

2. slave在增量同步时,master的积压缓存里没有需要同步的数据

部分重同步(增量同步)

完整重同步(全量同步)会消耗master大量的CPU、内存和磁盘I/O资源。如果slave跟master网络只断开一小会,期间master增加的数据并不多。slave再跟master重连后,如果还要执行完整重同步就很不划算了。所以redis提供了部分重同步(增量同步)。

部分重同步涉及如下几个概念

  • 复制偏移量(offset)
  • 复制积压缓冲区(replication_backlog_buffer)
复制偏移量(offset)

主从服务器都会分别维护各自的复制偏移量。

  • 主服务器每次向从服务器传播 n 个字节数据时,都会将自己的复制偏移量加 n。
  • 从服务器接受主服务器传来的数据时,也会将自己的复制偏移量加 n。

举个例子:

若当前主服务器的复制偏移量为 10000,此时向从服务器传播 30 个字节数据,结束后复制偏移量为 10030。

此时从服务器的复制偏移量为 10000,如果从服务器接收到这 30 个字节数据,结束后复制偏移量为 10030;如果从服务器还没接收这 30 个字节数据就断线了,然后重新连接上之后,该从服务器的复制偏移量是10000,此时主从数据不一致,从服务器会向主服务器发送 psync 命令。

复制积压缓冲区(replication_backlog_buffer)
  • master有一个复制积压缓冲区(replication_backlog_buffer),该缓冲区有且只有一个,所有slave共享此缓冲区,其作用在于备份最近主库发送给从库的数据。
  • 复制积压缓冲区默认大小 1MB。由下列参数配置
# repl-backlog-size 1mb		//积压缓存默认大小为1M,如果超过,数据覆盖
  • 复制积压缓冲区是一个固定长度,先进先出的队列。当主服务器进行命令传播时,不仅会将命令发送给从服务器,还会发送一份到复制积压缓冲区,作为写命令的备份。复制积压缓冲区的构造如下:

在这里插入图片描述

  • 由上面的构造图可知,除了存储最近的写命令,复制积压缓冲区中还存储了每个字节相应的复制偏移量,由于复制积压缓冲区是固定大小先进先出的队列,所以它总是保存的是最近redis执行的命令,早期的命令会逐步删除。

  • 当从服务器向主服务器发送 psync 命令时,会将自己的复制偏移量带上,主服务器就可以对从服务器传来的复制偏移量和自己复制积压缓冲区的偏移量做对比:

    • 若复制积压缓冲区存在从服务器的复制偏移量 + 1 后的数据,则进行部分重同步,否则进行完整重同步
部分重同步执行过程

执行过程如下:

  1. slave向master发送数据同步指令(psync),向master传输slave的master_repid、offset等信息。
  2. master收到数据同步指令后,如果发现master_repid != 自己的repid,则执行完整重同步(全量同步);如果发现master_repid == 自己的repid,则master会去找到你这个slave还有哪些数据没有同步。
  3. 通过slave传过来的offset和自己在复制积压缓冲区的数据的offset作比较,master就能够知道它有哪些数据没有同步。
    • 复制积压缓冲区存在从服务器的offset + 1 后的数据,就执行增量同步操作。
    • 否则,执行全量同步操作。

命令传播(指令同步)

经过上述的同步操作,此时主从的数据库状态其实已经一致了,但这种一致的状态的并不是一成不变的。

主服务器还会接受新的写命令,执行完新的写命令后,主从的数据库状态又不一致。

为了再次让主从数据库状态一致,主服务器就需要向从服务器执行命令传播操作 ,即把刚才造成不一致的写命令,发送给从服务器去执行。从服务器执行完成之后,主从数据库状态就又恢复一致了

心跳检测

主从同步有同步和命令传播 2 个步骤。

当完成了同步之后,主从服务器就会进入命令传播阶段,此时从服务器会以每秒 1 次的频率,向主服务器发送命令:REPLCONF ACK <replication_offset> 其中 replication_offset 是从服务器当前的复制偏移量

发送这个命令主要有三个作用:

  • 检测主从服务器的网络状态
  • 辅助实现 min-slaves 选项
  • 检测命令丢失(若丢失,主服务器会将丢失的写命令重新发给从服务器)

Redis sentinel哨兵

概述

虽然Redis主从解决了比如负载、数据备份等问题。但是,我们发现如果master挂了,slave不会直接升级为master,必须手动把slave升级为master才能恢复主从网络。我们不希望master挂了后,还需要人半夜来解决这件事情,来启动slave容灾。所以就有了我们的哨兵集群,以及我们后面的cluster集群。

哨兵(Redis sentinel)为Redis提供了高可用性。并且提供了监测、通知、自动故障转移、配置提供等功能。

  • 监控:能够监控我的Redis各实例是否正常工作。
  • 通知:如果Redis的实例出现问题, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障转移:当master宕机,可以把其中一个slave自动升级为master。
  • 配置提供:sentinel可以提供Redis的master实例地址,那么客户端只需要跟sentinel进行连接,master挂了后会提供新的master。如下图

在这里插入图片描述

哨兵故障转移流程

发现master故障

  1. 每个Sentinel节点会每隔1秒对主节点、从节点、其他Sentinel节点发送ping命令做心跳检测。当这些节点超过down-after-milliseconds没有进行有效回复,Sentinel节点就会对该节点做失败判定,这个时候不会触发故障转移,只会标记一个状态,这个状态就是SDOWN(Subjectively Downcondition),也就是主观下线。
  2. 当Sentinel主观下线的节点是master节点时,该Sentinel节点会通过sentinel is-master-down-by-addr命令向其他Sentinel节点询问对主节点的判断,当超过Quorum(法定人数)的sentinel都认为master不可用,都标记SDOWN状态,这个时候,master可能就
    真的是down了。那么就会将master标为ODOWN(Objectively Downcondition 客观下线)。

Sentinel节点领导者选举

  1. 当master状态是ODOWN的时候,我们就需要去触发故障转移,但是有这么多的sentinel,我们需要选一个sentinel节点作为领导者去做故障转移这件事情,并且这个sentinel在做故障转移的时候,其他sentinel不能进行故障转移。
  2. 选举过程有2个因素:
    • Quorum(法定人数)如果小于等于Sentinel节点数的一半,那么必须超过半数的sentinel授权,你才能去做故障迁移,比如5台 sentinel,你配置的Quorum=2,那么选举的时候必须有3(5台的一半以上)节点同意。
    • Quorum如果大于一半,那么必须Quorum个数的sentinel授权,故障迁移才能启动。

故障转移

  1. 当领导者Sentinel节点被选出,就执行故障转移,选择1个slave升级成master。选择条件如下:
    • 过滤:“不健康”(主观下线、断线)、5秒内没有回复过Sentinel节点ping响应、与主节点失联超过超时时间(down-after-milliseconds)* 10秒的节点。
    • 优先级:选择replica-priority最小的从节点列表,如果存在则返回,不存在则继续。replica-priority越小表示优先级越高,但是配置为0的时候,永远没有资格升为master。
    • 已复制数据的偏移量:比较slave的赋值的数据偏移量,数据最新的优先升级为master,如果存在则返回,不存在则继续。
    • Run ID (每个实例启动都会有个Run ID ):选择runid最小的从节点。
  2. Sentinel领导者节点会对上一步选出来的从节点执行slaveof no one命令,让其成为master节点。
  3. Sentinel领导者节点会向剩余的从节点发送命令,让它们成为新主节点的从节点。
  4. Sentinel节点集合会将原来的主节点更新为从节点,并保持着对其关注,当其恢复后命令它去复制新的主节点。

哨兵导致的数据一致性问题解析

官方建议配置至少3个sentinel节点。原因:

  1. 如果只有1个sentinel实例,则这个实例挂了就不能保证sentinel的高可用性
  2. 如果有2个sentinel实例,容易产生脑裂问题。

脑裂问题

在这里插入图片描述

如图,有个1主1从2哨兵的网络,如果配置quorum=1。在sentinel2失去master的感知的时候,

  1. 因为127跟128网络断开,这个时候会触发主观下线,同时,sentinel2只能连接到1个sentinel,也满足半数以上原则(只有1个sentinel2)。 所以sentinel2可以通过领导者选举,做故障转移。
  2. sentinel2会将128的slave升级为master,此时就出现了2个master,这个情况叫作脑裂。并且客户端会连接到2个master。
  3. 此时2个master都会写入数据,当网络恢复后,127会变成slave,127的数据会从128去拿取,这个时候127的数据就会丢失.

脑裂问题其实就是集群中产生2个master,导致client会从不同的master写数据,从而在master恢复的时候会导致数据丢失。

不管多少个节点,都可能会出现脑裂问题

解决方案

redis.conf 修改属性,通过活跃slave节点数和数据同步延迟时间来限制master节点的写入操作。

# master 至少有 x 个副本连接。
min-slaves-to-write x
# 主从之间的数据复制和同步的延迟不能超过 x 秒。
min-slaves-max-lag x

为什么redis推荐奇数个节点

其主要原因还是从成本上考虑的,因为奇数个节点和偶数个节点允许宕机的节点数是一样的,比如3个节点和4个节点都只允许宕机一台。

Redis Cluster

sentinel提供了比如监控、自动故障转移、客户端配置等高可用的方案,但是没有分片功能。
所谓的分片:就是我希望把数据分布到不同的节点。这样如果某些节点异常,其他数据能正常提供服务,跟我们微服务的思想很相似。

Redis Cluster就提供了这样的功能。

  1. 多个节点之间的数据拆分,也就是数据分片功能。
  2. 当某些节点遇到故障的时候,其他的节点还能继续服务。

hash slot(虚拟槽)

分片要做的事情就是要把不同的数据放到不同的实例里面去。就相当于我们分表,不同的数据放到不同的表里。 那么如何进行分片?

普通取模问题

参考hashMap,我们有个方法:

计算key的hash值,然后节点个数取模,得到存入的节点下标。比如节点个数是3,那么取模后得到0-2的值,每个值代表一个节点。但是这种取模方法有一个问题,假如我做了实例的扩容与缩容,那么全部数据要进行迁移。比如我之前是3台,扩容到4台,那么所有的数据都必须重新rehash。

所以,Redis里面提出了一个Hash槽,也叫作虚拟槽的概念。什么是虚拟槽,其实就是虚拟节点。

虚拟槽

Redis cluster中有16384个虚拟槽(2^14)。

  • 根据key通过CRC16 取模 16383 得到一个0到16383的值,计算公式:slot = CRC16(key) & 16383。得到的值,就代表这个key在哪个虚拟槽。
  • 虚拟槽会跟我们的真实节点进行对应,这个关系是可以变更的。可以设置某个实例节点包含哪些虚拟槽,但是至少得有3个主实例节点,主节点可以有自己的从节点。

假如,我们现在有6台实例,三主三从。 主跟槽的对应关系可以如下

master1 0-5460虚拟槽
master2 5461-10922虚拟槽
master3 10923-16383虚拟槽
127.0.0.1:6380> cluster nodes //查看当前节点的虚拟槽信息的指令
  • 由此可见,每次节点的扩容与缩容,只需要改变节点跟虚拟槽的关系即可,数据迁移也只迁移一部分数据。

比如上述例子要增加一个节点,主跟槽的对应关系可以做如下变更。那只需要迁移5461-6460虚拟槽中数据即可。

master1 0-5460虚拟槽
master4 5461-6460虚拟槽
master2 6461-10922虚拟槽
master3 10922-16383虚拟槽

添加节点(集群扩容)

  1. 启动集群

  2. 启动需要添加的节点,这里要添加的节点是:127.0.0.1:6436

./redis-server ../redis.conf
  1. 将节点添加进集群
./redis-cli --cluster add-node 127.0.0.1:6436 127.0.0.1:6435

查看node节点信息,从最后一行可以看到,新节点已经加进集群

127.0.0.1:6430> cluster nodes
082f87e4bdebbc424a9a996048e085c4372ab515 127.0.0.1:6431@16431 slave 63dc100e63a583c8dcb77161c7c4c9ae4f866b7e 0 1667488539000 8 connected
a0bf7101c4d885532fc76946a4e13c0e5c8043d7 127.0.0.1:6430@16430 myself,slave 999e5ed482bbfffde7e9508e832da7f51200a583 0 1667488540000 7 connected
63dc100e63a583c8dcb77161c7c4c9ae4f866b7e 127.0.0.1:6434@16434 master - 0 1667488540000 8 connected 5461-10922
999e5ed482bbfffde7e9508e832da7f51200a583 127.0.0.1:6433@16433 master - 0 1667488541138 7 connected 0-5460
9250d1d78c76e405262e4791936402e3e9d868bc 127.0.0.1:6435@16435 slave bc9c6cb3bd9367724977e72727eb67d587905af8 0 1667488540135 3 connected
bc9c6cb3bd9367724977e72727eb67d587905af8 127.0.0.1:6432@16432 master - 0 1667488539135 3 connected 10923-16383
b49a91a9bf80fcfdfe96b8cb2d1a56b4f752e633 127.0.0.1:6436@16436 master - 0 1667488538132 0 connected

数据迁移

  1. 分配slot,做数据迁移
redis-cli --cluster reshard 127.0.0.1:6436

该命令需要交互实现,也可以使用脚本命令。

交互内容:

  • How many slots do you want to move (from 1 to 16384)?(需要迁移多少个槽)

  • What is the receiving node ID?(接受 slot 槽的节点ID)

  • Please enter all the source node IDs.
    Type ‘all’ to use all the nodes as source nodes for the hash slots.
    Type ‘done’ once you entered all the source nodes IDs.(哪些节点需要导出,all是自动分配,done是手动分配,扩容用all即可)

  • Do you want to proceed with the proposed reshard plan (yes/no)?(确认信息,选yes)

脚本命令:

redis-cli --cluster reshard 127.0.0.1:6436 --cluster-from bc9c6cb3bd9367724977e72727eb67d587905af8,63dc100e63a583c8dcb77161c7c4c9ae4f866b7e,999e5ed482bbfffde7e9508e832da7f51200a583 --cluster-to b49a91a9bf80fcfdfe96b8cb2d1a56b4f752e633 --cluster-slots 4000 --cluster-yes

至此,添加master节点完成。

  1. 添加slave节点
redis-cli --cluster add-node 127.0.0.1:6437 127.0.0.1:6436 --cluster-slave --cluster-master-id b49a91a9bf80fcfdfe96b8cb2d1a56b4f752e633

说明:

  • add-node: 后面的分别跟着新加入的 slave 和 slave 对应的 master
  • –cluster-slave:表示加入的是 slave 节点
  • –cluster-master-id:表示 slave 对应的 master 的 node ID

删除节点(集群缩容)

假设要删除127.0.0.1:6436节点:

  1. 如果删除是主节点,必须先对其做数据迁移,让主节点为空。所以这里先对127.0.0.1:6436节点做数据迁移
redis-cli --cluster reshard 127.0.0.1:6432

#redis-cli --cluster reshard <数据迁移的目标节点的ip:port>

交互内容:

  • How many slots do you want to move (from 1 to 16384)?

    • 写入127.0.0.1:6436包含的slot数量
  • What is the receiving node ID?

    • 选择127.0.0.1:6432的节点ID
  • Please enter all the source node IDs.
    Type ‘all’ to use all the nodes as source nodes for the hash slots.
    Type ‘done’ once you entered all the source nodes IDs.

    • 先写入导出的节点的Id,这里是127.0.0.1:6436
    • 然后写入done
  • Do you want to proceed with the proposed reshard plan (yes/no)?

    • yes
  1. 执行节点删除
redis-cli --cluster del-node 127.0.0.1:6436 b49a91a9bf80fcfdfe96b8cb2d1a56b4f752e633

#redis-cli --cluster del-node <待删除节点的ip:port> <待删除节点的id>

参考资料

  • Redis命令

https://zhuanlan.zhihu.com/p/359563484

https://www.processon.com/view/link/62cd1c400e3e74070446a5b2

  • redis集群

https://blog.csdn.net/hebtu666/article/details/114827837?ops_request_misc=%7B%22request%5Fid%22%3A%22166731098216782425189807%22%2C%22scm%22%3A%2220140713.130102334.pc%5Fblog.%22%7D&request_id=166731098216782425189807&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-4-114827837-null-null.nonecase&utm_term=redis&spm=1018.2226.3001.4450)

  • redis哨兵

https://zhuanlan.zhihu.com/p/426497450

  • 脑裂问题

https://www.cnblogs.com/dcdcyyy/p/14275124.html

  • 为什么redis推荐奇数个节点

https://blog.csdn.net/qq32933432/article/details/105785571

  • 主从同步

https://zhuanlan.zhihu.com/p/55532249

  • 流程图

https://www.processon.com/view/link/62cd1c400e3e74070446a5b2

  • redis cluster扩容和缩容

https://blog.csdn.net/lzb348110175/article/details/122168638

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

Redis系列(七)Redis主从、哨兵、cluster集群方案解析 的相关文章

  • 在 JTable 中移动行

    我使用 MVC 模式 并且有一个如下所示的 JTable List
  • ElasticBeanstalk Java,Spring 活动配置文件

    我正在尝试通过 AWS ElasticBeanstalk 启动 spring boot jar 一切正常 配置文件为 默认 有谁知道如何为 java ElasticBeanstalk 应用程序 不是 tomcat 设置活动配置文件 spri
  • AES 加密 Java/plsql

    我需要在Java和plsql DBMS CRYPTO for Oracle 10g 上实现相同的加密 解密应用程序 两种实现都工作正常 但这里的问题是我对相同纯文本的加密得到了不同的输出 下面是用于加密 解密过程的代码 Java 和 PLS
  • 在Windows上安装Java 11 OpenJDK(系统路径问题)

    Java 11 最近发布了 众所周知 这个版本没有安装文件 当然 要在没有安装程序的情况下安装 Java 我将系统设置 PATH 和 JAVA HOME 设置为解压缩 Java 11 的文件夹的地址 根据对类似问题的已接受回复建议 唯一的事
  • 如何测试 JUnit 测试的 Comparator?

    我需要测试 Compare 方法 但我对如何测试感到困惑 我可以看看该怎么做吗 public class MemberComparator implements Comparator
  • Android Studio 在编译时未检测到支持库

    由于 Android Studio 将成为 Android 开发的默认 IDE 因此我决定将现有项目迁移到 Android studio 中 项目结构似乎不同 我的项目中的文件夹层次结构如下 Complete Project gt idea
  • java中删除字符串中的特殊字符?

    如何删除字符串中除 之外的特殊字符 现在我用 replaceAll w s 它删除了所有特殊字符 但我想保留 谁能告诉我我该怎么办 Use replaceAll w s 我所做的是将下划线和连字符添加到正则表达式中 我添加了一个 连字符之前
  • 如何在 Java 中禁用 System.out 以提高速度

    我正在用 Java 编写一个模拟重力的程序 其中有一堆日志语句 到 System out 我的程序运行速度非常慢 我认为日志记录可能是部分原因 有什么方法可以禁用 System out 以便我的程序在打印时不会变慢 或者我是否必须手动检查并
  • hibernate总是自己删除表中的所有数据

    您好 我正在开发一个 spring mvc 应用程序 它使用 hibernate 连接到存储文件的 mysql 数据库 我有两个方法 一个方法添加我选择的特定文件路径中的所有文件 另一种方法调用查询以返回从 mysql 存储的文件列表 问题
  • 使用替换字符串中多个单词的最有效方法[重复]

    这个问题在这里已经有答案了 此刻我正在做 Example line replaceAll replaceAll cat dog replaceAll football rugby 我觉得那很丑 不确定有更好的方法吗 也许循环遍历哈希图 ED
  • Clip 在 Java 中播放 WAV 文件时出现严重延迟

    我编写了一段代码来读取 WAV 文件 大小约为 80 mb 并播放该文件 问题是声音播放效果很差 极度滞后 你能告诉我有什么问题吗 这是我的代码 我称之为doPlayJframe 构造函数内的函数 private void doPlay f
  • 在具有相同属性名称的不同数据类型上使用 ModelMapper

    我有两节课说Animal AnimalDto我想用ModelMapper将 Entity 转换为 DTO 反之亦然 但是对于具有相似名称的一些属性 这些类应该具有不同的数据类型 我该如何实现这一目标 动物 java public class
  • 检查 Android 手机上的方向

    如何查看Android手机是横屏还是竖屏 当前配置用于确定要检索的资源 可从资源中获取Configuration object getResources getConfiguration orientation 您可以通过查看其值来检查方向
  • 从 android 简单上传到 S3

    我在网上搜索了从 android 上传简单文件到 s3 的方法 但找不到任何有效的方法 我认为这是因为缺乏具体步骤 1 https mobile awsblog com post Tx1V588RKX5XPQB TransferManage
  • 尝试使用 Ruby Java Bridge (RJB) gem 时出现错误“无法创建 Java VM”

    我正在尝试实现 Ruby Java Bridge RJB gem 来与 JVM 通信 以便我可以运行 Open NLP gem 我在 Windows 8 上安装并运行了 Java 所有迹象 至少我所知道的 都表明 Java 已安装并可运行
  • Java直接内存:在自定义类中使用sun.misc.Cleaner

    在 Java 中 NIO 直接缓冲区分配的内存通过以下方式释放 sun misc Cleaner实例 一些比对象终结更有效的特殊幻像引用 这种清洁器机制是否仅针对直接缓冲区子类硬编码在 JVM 中 或者是否也可以在自定义组件中使用清洁器 例
  • Tomcat 6找不到mysql驱动

    这里有一个类似的问题 但关于类路径 ClassNotFoundException com mysql jdbc Driver https stackoverflow com questions 1585811 classnotfoundex
  • 如何配置eclipse以保持这种代码格式?

    以下代码来自 playframework 2 0 的示例 Display the dashboard public static Result index return ok dashboard render Project findInv
  • 如何修复“sessionFactory”或“hibernateTemplate”是必需的问题

    我正在使用 Spring Boot JPA WEB 和 MYSQL 创建我的 Web 应用程序 它总是说 sessionFactory or hibernateTemplate是必需的 我该如何修复它 我已经尝试过的东西 删除了本地 Mav
  • 中断连接套接字

    我有一个 GUI 其中包含要连接的服务器列表 如果用户单击服务器 则会连接到该服务器 如果用户单击第二个服务器 它将断开第一个服务器的连接并连接到第二个服务器 每个新连接都在一个新线程中运行 以便程序可以执行其他任务 但是 如果用户在第一个

随机推荐

  • EIoU和Focal-EIoU Loss

    1 论文 论文题目 Focal and Efficient IOU Loss for Accurate Bounding Box Regression 2 引言 CIoU Loss虽然考虑了边界框回归的重叠面积 中心点距离 高宽比 但是其公
  • 第一章:宇宙第一IDE--Visual Studio

    数据结构 是指一种计算机存储 组织数据的方式 IDE Integrated Development Environment 的缩写 表示 集成开发环境 它是一种用于提供程序开发环境的应用程序 一般包括代码编辑器 编译器 调试工具和图形化用户
  • Java调用exe程序

    String exePath D Xftp6 Xftp exe BufferedReader br null BufferedReader brError String line null try String cmd D Xftp6 Xf
  • MATLAB函数句柄

    1 何为函数句柄 函数句柄也是MATLAB中的一种常见的数据类型 它的地位类似于其它计算机语言里的函数对象 Javascript Python 函数指针 C 或者函数引用 Perl 它的作用是将一个函数封装成一个变量 使其能够像其它变量一样
  • 【NLP】自然语言处理技术在自动生成足球比赛战报上的应用

    1 背景介绍 自动生成新闻看似是一个很成熟的技术 很多年前就有各种应用 但是深入了解后我们可以发现机器自动生成的文章一般都是复述一些数字和简单的趋势变化 所以自动生成新闻的技术广泛应用在金融 体育领域 原因就是这类报道需要基于一定的事实 而
  • 模型调参之网格搜索与随机搜索

    模型调参之网格搜索与随机搜索 网格搜索法 GridSearchCV GridSearchCV GridSearchCV可以拆分成GridSearch和CV两部分 即网格搜素和交叉验证 GridSearch系统地遍历多种参数组合 通过交叉验证
  • 一文讲透彻!RobotFramwork测试框架教程(全能)

    Robot Framwork在业界早已名声大振 有很多刚学自动化测试的伙伴问我 有没有不需要编程就可以玩自动化的方法 有吗 有的 Robot Framwork 我们今天就一篇文章 把它讲得明明白白 一 Robot Framwork简述 Ro
  • 宅男福利!程序员周末看片神器,关键还开源

    本文源自自公众号开源最前线 ID OpenSourceTop 猿妹整理 别人眼中的程序员一定是这样的 每天有接不完的需求 写不完的代码 改不完的Bug 但大多数程序员偶尔也是有周末的 你是否有出现这种情况 连续加了好几天的班 好不容易迎来一
  • Python查询MySQL数据库并输出相应信息

    场景描述 将fork的编号与ip信息存储在了MySQL中 数据库为forklift 数据表名为fork info 存储格式为id num ip 那么如何用python去查询这些信息呢 分析 根据提供的MySQL表结构 想从名为fork in
  • 【千律】C++基础:打开并下载网页 -- ShellExecuteEx 和 URLDownloadToFile 函数

    include
  • Elasticsearch 7 系列(3) —— 核心概念

    目录 集群 cluster 节点 node 索引 index 类型 type 要学好Elasticsearch 就得先对Elasticsearch中的概念有所了解 接下来我们就重点说说Elasticsearch中的集群 节点 索引 类型 文
  • 多个if语句并列_使用if-then 语句

    最基本的结构化命令就是if then语句 if then语句有如下格式 if command then commands fi 简单的例子 cat test1 sh bin bash testing the if statementif p
  • 开发工具链-DevOps_阿里云云效

    简介 阿里云效官网 DevOps Development和Operations的组合词 是一组过程 方法与系统的统称 用于促进开发 应用程序 软件工程 技术运营和质量保障 QA 部门之间的沟通 协作与整合 百度百科 快速开始 1 云效首页
  • 给导航网站新增了一些免费影视网站,欢迎体验

    使用时建议使用火狐浏览器 并安装广告屏蔽插件 这样就没有广告 视频内的广告千万不要相信 其余安心食用 地理导航 地理上网从这里开始
  • VS Code Remote Development

    配置VSCode Remote Development 1 Ubuntu 上启用 SSH 1 打开终端 并且安装openssh server软件包 sudo apt update sudo apt install openssh serve
  • 图像处理岗位面试题搜罗汇总

    传统图像处理部分 图像处理基础知识 彩色图像 灰度图像 二值图像和索引图像区别 彩色图像 RGB图像 灰度图像 0 255像素值 二值图像 0和1 用于掩膜图像 索引图像 在灰度图像中 自定义调色板 自定义输出256种颜色值 常用的图像空间
  • java 泛型 作用与定义

    1 泛型方法的定义和使用 public static void main String args throws ClassNotFoundException String str get 哈士奇 world System out print
  • Mac显示放大镜

    设置快捷键 系统默认是不开启热键的 如果需要设置 操作如下 设置 system preferences gt accessibility 在左侧找到room 进入配置窗口 按如上配置后 按住option键 然后两指向上就可以放大 两指向下就
  • 这座城市引领大模型浪潮!80余个AI大模型,一半集结在这里!

    刚刚结束的2023全球数字经济大会上 人工智能高峰论坛掀起了一股热潮 大型模型的发展和应用成为了会议的亮点 而作为这次盛会的主办方之一 北京市已经成为了这场人工智能革命的领先力量 作为人工智能产业的引领者 北京不负众望 国内已有80余个大型
  • Redis系列(七)Redis主从、哨兵、cluster集群方案解析

    文章目录 Redis主从 主从数据同步 同步 建立连接 完整重同步 全量同步 触发条件 部分重同步 增量同步 复制偏移量 offset 复制积压缓冲区 replication backlog buffer 部分重同步执行过程 命令传播 指令