redis集群拓扑结构自动更新:使用Lettuce连接Cluster集群实例时异常处理

2023-11-16

问题
使用lettuce连接Cluster集群实例,实例执行规格变更后,分片数有变化时,部分槽位(Slot)会迁移到新分片上,当客户端连接到新分片时会出现以下异常问题

java.lang.IllegalArgumentException: Connection to 100.123.70.194:6379 not allowed. This connection point is not known in the cluster view
exceptionStackTrace
io.lettuce.core.cluster.PooledClusterConnectionProvider.getConnectionAsync(PooledClusterConnectionProvider.java:359)
io.lettuce.core.cluster.ClusterDistributionChannelWriter.write(ClusterDistributionChannelWriter.java:93)
io.lettuce.core.cluster.ClusterCommand.complete(ClusterCommand.java:56)
io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:563)
io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:516)
org.springframework.dao.QueryTimeoutException: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 5 second(s)
at org.springframework.data.redis.connection.lettuce.LettuceExceptionConverter.convert(LettuceExceptionConverter.java:70)

问题
redis连接后,隔一段时间,连接慢
Redis Cluster集群模式下master宕机或网络抖动等原因,主从切换期间 报错:Redis command timed out等问题

Connection to X not allowed. This connection point is not known in the cluster view.
官网
参考

解决方案

开启redis client的集群拓扑刷新功能,不同客户端,采用不同处理方式

  • jedis client默认自动支持(由于jedis通过自身异常反馈来识别重连、刷新服务端的集群信息机制,保证其自动故障恢复)
  • luttuce client 默认未开启,需要手动开启刷新
    • springboot 1.x之前版本默认使用jedis,无需要手动开启刷新
    • springboot 2.x,redis client默认为Lettuce,默认不支持拓扑刷新解决方案:
      • 使用jedis,不需要手动指定开启刷新
      • 使用lettuce,需要设置开启刷新节点拓扑策略
    • springboot 2.3.0开始,支持集群拓扑刷新功能,属性配置开启即可

springboot 2.0.X

方法一

使用letture方式连接redis,需要设置开启刷新节点拓扑刷新策略

使用 RedisClusterClient.reloadPartitions 自动 reload pattitions

#redis cluster config
#RedisCluster集群节点及端口信息
spring.redis.cluster.nodes=192.168.50.29:6380,192.168.50.29:6381,192.168.50.29:6382,192.168.50.29:6383,192.168.50.29:6384,192.168.50.29:6385
#Redis密码
spring.redis.password=
#在群集中执行命令时要遵循的最大重定向数目
spring.redis.cluster.max-redirects=6
#Redis连接池在给定时间可以分配的最大连接数。使用负值无限制
spring.redis.jedis.pool.max-active=1000
#以毫秒为单位的连接超时时间
spring.redis.timeout=2000
#池中“空闲”连接的最大数量。使用负值表示无限数量的空闲连接
spring.redis.jedis.pool.max-idle=8
#目标为保持在池中的最小空闲连接数。这个设置只有在设置max-idle的情况下才有效果
spring.redis.jedis.pool.min-idle=5
#连接分配在池被耗尽时抛出异常之前应该阻塞的最长时间量(以毫秒为单位)。使用负值可以无限期地阻止
spring.redis.jedis.pool.max-wait=1000
#redis cluster只使用db0
spring.redis.index=0
import io.lettuce.core.ReadFrom;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * Redis配置类
 *
 * @author 007
 */
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfiguration {
    @Autowired
    private RedisProperties redisProperties;

    @Bean(destroyMethod = "destroy")
    public LettuceConnectionFactory redisConnectionFactory() {
        // redis单节点
        if (null == redisProperties.getCluster() || null == redisProperties.getCluster().getNodes()) {
            RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(),
                    redisProperties.getPort());
            configuration.setPassword(redisProperties.getPassword());
            return new LettuceConnectionFactory(configuration);
        }

        // redis集群
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
        redisClusterConfiguration.setPassword(redisProperties.getPassword());
        redisClusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());

        GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
        genericObjectPoolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());
        genericObjectPoolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());
        genericObjectPoolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());
        genericObjectPoolConfig.setMaxWaitMillis(redisProperties.getLettuce().getPool().getMaxWait().getSeconds());

        // 支持自适应集群拓扑刷新和动态刷新源
        ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
                .enableAllAdaptiveRefreshTriggers()
                // 开启自适应刷新
                .enableAdaptiveRefreshTrigger()
                // 开启定时刷新
                .enablePeriodicRefresh(Duration.ofSeconds(5))
                .build();

        ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                .topologyRefreshOptions(clusterTopologyRefreshOptions).build();
			/*
			 ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
			                                 .topologyRefreshOptions(clusterTopologyRefreshOptions)//拓扑刷新
			                                 .disconnectedBehavior(ClientOptions.DisconnectedBehavior.REJECT_COMMANDS)
			                                 .autoReconnect(true)
			                                 .socketOptions(SocketOptions.builder().keepAlive(true).build())
			                       .validateClusterNodeMembership(false)// 取消校验集群节点的成员关系
			                                 .build();
			*/

        LettuceClientConfiguration lettuceClientConfiguration = LettucePoolingClientConfiguration.builder()
                .poolConfig(genericObjectPoolConfig)
                .readFrom(ReadFrom.SLAVE_PREFERRED) // 使用ReadFrom.SLAVE_PREFERRED读写分离
                .clientOptions(clusterClientOptions).build();

        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
        lettuceConnectionFactory.setShareNativeConnection(false);// 是否允许多个线程操作共用同一个缓存连接,默认 true,false 时每个操作都将开辟新的连接
        lettuceConnectionFactory.resetConnection();// 重置底层共享连接, 在接下来的访问时初始化
        return lettuceConnectionFactory;
    }

 	//自定义一个RedisTemplate
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(@Qualifier("lettuceConnectionFactoryUvPv") LettuceConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 一定要注入RedisTemplate和redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        template.setConnectionFactory(factory);
 
        //Json序列化配置
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(om.getPolymorphicTypeValidator());
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //解决序列化问题
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        jackson2JsonRedisSerializer.setObjectMapper(om);
 
        //String的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
 
        //key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
 
        //value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
 
        //hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
 
        return template;
    }
}

import io.lettuce.core.ClientOptions;
import io.lettuce.core.cluster.ClusterClientOptions;
import io.lettuce.core.cluster.ClusterTopologyRefreshOptions;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author : 007
 * @version : 2.0
 * @date : 2020/7/27 10:19
 */
@Component
public class RedisConfig {

    @Autowired
    private RedisProperties redisProperties;

    public GenericObjectPoolConfig<?> genericObjectPoolConfig(RedisProperties.Pool properties) {
        GenericObjectPoolConfig<?> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(properties.getMaxActive());
        config.setMaxIdle(properties.getMaxIdle());
        config.setMinIdle(properties.getMinIdle());
        if (properties.getTimeBetweenEvictionRuns() != null) {
            config.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRuns().toMillis());
        }
        if (properties.getMaxWait() != null) {
            config.setMaxWaitMillis(properties.getMaxWait().toMillis());
        }
        return config;
    }

    @Bean(destroyMethod = "destroy")
    public LettuceConnectionFactory lettuceConnectionFactory() {

        //开启 自适应集群拓扑刷新和周期拓扑刷新
        ClusterTopologyRefreshOptions clusterTopologyRefreshOptions =  ClusterTopologyRefreshOptions.builder()
                // 开启全部自适应刷新
                .enableAllAdaptiveRefreshTriggers() // 开启自适应刷新,自适应刷新不开启,Redis集群变更时将会导致连接异常
                // 开启自适应刷新
                //.enableAdaptiveRefreshTrigger()
                // 自适应刷新超时时间(默认30秒)
                .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30)) //默认关闭开启后时间为30秒
                // 开周期刷新
                .enablePeriodicRefresh(Duration.ofSeconds(20))  // 默认关闭开启后时间为60秒 ClusterTopologyRefreshOptions.DEFAULT_REFRESH_PERIOD 60  .enablePeriodicRefresh(Duration.ofSeconds(2)) = .enablePeriodicRefresh().refreshPeriod(Duration.ofSeconds(2))
                .build();

        // https://github.com/lettuce-io/lettuce-core/wiki/Client-Options
        ClientOptions clientOptions = ClusterClientOptions.builder()
                .topologyRefreshOptions(clusterTopologyRefreshOptions)
                .build();

        LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
                .poolConfig(genericObjectPoolConfig(redisProperties.getJedis().getPool()))
                //.readFrom(ReadFrom.MASTER_PREFERRED)
                .clientOptions(clientOptions)
                .commandTimeout(redisProperties.getTimeout()) //默认RedisURI.DEFAULT_TIMEOUT 60
                .build();

        List<String> clusterNodes = redisProperties.getCluster().getNodes();
        Set<RedisNode> nodes = new HashSet<RedisNode>();
        clusterNodes.forEach(address -> nodes.add(new RedisNode(address.split(":")[0].trim(), Integer.valueOf(address.split(":")[1]))));

        RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
        clusterConfiguration.setClusterNodes(nodes);
        clusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
        clusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());

        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfiguration, clientConfig);
        // lettuceConnectionFactory.setShareNativeConnection(false); //是否允许多个线程操作共用同一个缓存连接,默认true,false时每个操作都将开辟新的连接
        // lettuceConnectionFactory.resetConnection(); // 重置底层共享连接, 在接下来的访问时初始化
        return lettuceConnectionFactory;
    }
}

public LettuceConnectionFactory redisConnectionFactory(ClientResources clientResources) {
    // redis单节点
    if (null == redisProperties.getCluster() || null == redisProperties.getCluster().getNodes()) {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(redisProperties.getHost(),
                redisProperties.getPort());
        configuration.setPassword(redisProperties.getPassword());
        return new LettuceConnectionFactory(configuration);
    }

    ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
            // //按照周期刷新拓扑
            .enablePeriodicRefresh(Duration.ofSeconds(30))
            //根据事件刷新拓扑
            .enableAllAdaptiveRefreshTriggers()
            .build();

    ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
            //redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接
            .timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(10)))
            .topologyRefreshOptions(topologyRefreshOptions)
            .build();

    LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder()
            .clientResources(clientResources)
            .clientOptions(clusterClientOptions)
            .build();

    RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
    if (redisProperties.getCluster().getMaxRedirects() != null) {
        clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());
    }
    clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));

    return new LettuceConnectionFactory(clusterConfig, clientConfiguration);
}

方法二

改用jedis方式连接redis,使用jedis客户端的服务可以在主从切换后15秒恢复

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

注意配置文件把lettuce.pool换成jedis.pool

  • lettuce 配置信息

    spring.redis.lettuce.pool.max-active=10
    spring.redis.lettuce.pool.max-idle=10
    spring.redis.lettuce.pool.max-wait=10
    spring.redis.lettuce.pool.min-idle=5
    spring.redis.lettuce.shutdown-timeout=1S
    
  • jedis 配置信息

    spring.redis.jedis.pool.max-active=10
    spring.redis.jedis.pool.max-idle=10
    spring.redis.jedis.pool.max-wait=10
    spring.redis.jedis.pool.min-idle=5
    
    spring:
      redis:
        password: xxx
        host: 172.16.0.x
        port: 6579
        timeout: 5000
        jedis:
          pool:
                  #最大连接数据库连接数,设 0 为没有限制
            max-active: 8
                  #最大等待连接中的数量,设 0 为没有限制
            max-idle: 8
                  #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
            max-wait: -1ms
                  #最小等待连接中的数量,设 0 为没有限制
            min-idle: 0
        #lettuce:
          #pool:
            #max-active: ${redis.config.maxTotal:1024}
            #max-idle: ${redis.config.maxIdle:50}
            #min-idle: ${redis.config.minIdle:1}
            #max-wait: ${redis.config.maxWaitMillis:5000}
    

springboot 2.3

配置属性

spring.redis.lettuce.cluster.refresh.adaptive= true
spring.redis.lettuce.cluster.refresh.period=30000
spring:
  redis:
	lettuce:
	  cluster:
		refresh:
		  adaptive: true
		  period: 30000    # 30秒自动刷新一次
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

redis集群拓扑结构自动更新:使用Lettuce连接Cluster集群实例时异常处理 的相关文章

  • 如何从类似于 eclipse 的命令行创建可运行的 jar 文件

    我知道 eclipse 会生成一个可运行的 jar 文件 其中提取并包含在该 jar 文件中的所有库 jar 文件 从命令提示符手动创建 jar 文件时如何执行类似的操作 我需要将所有 lib jar 解压到类文件夹中吗 目前我正在使用 j
  • “grep -q”的意义是什么

    我正在阅读 grep 手册页 并遇到了 q 选项 它告诉 grep 不向标准输出写入任何内容 如果发现任何匹配 即使检测到错误 也立即以零状态退出 我不明白为什么这可能是理想或有用的行为 在一个程序中 其原因似乎是从标准输入读取 处理 写入
  • Scrapy FakeUserAgentError:获取浏览器时发生错误

    我使用 Scrapy FakeUserAgent 并在我的 Linux 服务器上不断收到此错误 Traceback most recent call last File usr local lib64 python2 7 site pack
  • 如何调用位于其他目录的Makefile?

    我正在尝试这样做 我想打电话给 make Makefile存在于其他目录中 abc可以使用位于不同目录中的 shell 脚本的路径 我该怎么做呢 由于 shell 脚本不允许我cd进入Makefile目录并执行make 我怎样才能编写she
  • 如何查明 Ubuntu 上安装了哪个版本的 GTK+?

    我需要确定 Ubuntu 上安装了哪个版本的 GTK 男人似乎不帮忙 这个建议 https stackoverflow com a 126145 会告诉您安装了哪个 2 0 的次要版本 不同的主要版本将具有不同的包名称 因为它们可以在系统上
  • 将数组传递给函数名称冲突

    Specs GNU bash 版本 3 1 17 无法升级 Premise 我一直在摆弄数组 我想知道是否有任何方法可以让函数的本地变量与所述函数外部的数组同名 Example 在下面的示例中 我将尝试显示该问题 Working bin b
  • 操作系统什么时候清除进程的内存

    进程在某些操作系统上成功或异常终止 操作系统何时决定擦除分配给该进程的内存 数据 代码等 在退出时或当它想为新进程分配内存时 这个清除内存分配过程在所有操作系统 winXP Win7 linux Mac 上都相同吗 据我了解 页表具有该进程
  • numpy 未定义符号:PyFPE_jbuf

    我正在尝试使用一百万首歌曲数据集 为此我必须安装 python 表 numpy cython hdf5 numexpr 等 昨天我设法安装了我需要的所有内容 在使用 hdf5 遇到一些麻烦之后 我下载了预编译的二进制包并将它们保存在我的 b
  • gethostbyname() 或 getnameinfo() 如何在后台工作?

    How gethostbyname or getnameinfo 在后台工作 include
  • 无法执行'x86_64-conda_cos6-linux-gnu-gcc':没有这样的文件或目录(pysam安装)

    我正在尝试安装 pysam 执行后 python path to pysam master setup py build 这个错误的产生是 unable to execute x86 64 conda cos6 linux gnu gcc
  • 在 Ubuntu 16.04 上找不到 printf.c

    我最近切换到Ubuntu 16 04 我在用vscode作为 Ubuntu 上的 IDE 我配置了其他语言 但我无法做到这一点C C 我创建c cpp properties json launch json tasks json 当我开始编
  • 如何让“grep”从文件中读取模式?

    假设有一个很大的文本文件 我只想打印与某些模式不匹配的行 显然 我可以使用egrep v patter1 pattern2 pattern3 现在 如果所有这些模式都在一个文本文件中怎么办 最好的制作方法是什么egrep从文件中读取模式 g
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • C 程序从连接到系统的 USB 设备读取数据

    我正在尝试从连接到系统 USB 端口的 USB 设备 例如随身碟 获取数据 在这里 我可以打开设备文件并读取一些随机原始数据 但我想获取像 minicom teraterm 这样的数据 请让我知道我可以使用哪些方法和库来成功完成此操作以及如
  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • Linux 桌面快捷方式和安装图标

    我需要添加什么到我的 spec文件来创建桌面快捷方式并在安装过程中为快捷方式分配一个图标 rpm 如果需要脚本 一个示例将非常有帮助 您在 Linux 下使用 desktop 文件作为图标 图标放置的位置取决于您使用的发行版和桌面环境 由于
  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • diff 文件仅比较每行的前 n 个字符

    我有2个文件 我们将它们称为 md5s1 txt 和 md5s2 txt 两者都包含a的输出 find type f print0 xargs 0 md5sum sort gt md5s txt 不同目录下的命令 许多文件被重命名 但内容保
  • 如何制作和应用SVN补丁?

    我想制作一个SVN类型的补丁文件httpd conf这样我就可以轻松地将其应用到其他主机上 If I do cd root diff Naur etc httpd conf httpd conf original etc httpd con
  • 并行运行 make 时出错

    考虑以下制作 all a b a echo a exit 1 b echo b start sleep 1 echo b end 当运行它时make j2我收到以下输出 echo a echo b start a exit 1 b star

随机推荐

  • TensorFlow搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)

    目录 I 前言 II CNN LSTM III 代码实现 3 1 数据处理 3 2 模型训练 测试 3 3 实验结果 IV 源码及数据 I 前言 前面已经写了很多关于时间序列预测的文章 深入理解PyTorch中LSTM的输入和输出 从inp
  • input标签限制只能输入数字

  • 操作系统实验:银行家算法(C语言)

    实验内容 某系统中进程P1 P2 P3 Pn 同时请求资源R1 R2 R3 Rn 已知t0时刻资源分配情况 参考下表 1 编写程序 分析当前系统状态是否安全 若系统安全 请输出安全序列 2 在系统安全的情况下 若有进程提出资源请求 如t1时
  • 人脸识别之caffe-face

    该论文为2016年的一篇ECCV ADiscriminative Feature Learning Approach for Deep Face Recognition 还是深圳先进院乔宇老师组的一篇 不管是思想还是效果都非常的棒 论文思想
  • Perl调用shell命令方法小结(system/反引号/exec)

    system 反引号 exec 为避免shell命令的特殊符号采用先变量定义的方法 system perl也可以用system调用shell的命令 它和awk的system一样 返回值也是它调用的命令的退出状态 root AX3sp2 ca
  • 单片机控制继电器实验

    单片机控制继电器实验 在各种自动控制设备中 都存在一个低压的自动控制电路与高压电气电路的互相连接问题 一方面要使低压的电子电路的控制信号能够控制高压电气电路的执行元件 如电动机 电磁铁 电灯等 另一方面又要为电子线路的电气电路提供良好的电隔
  • 如何安装以及用相关插件配置OBSIDIAN?

    之前看人推荐logseq就尝试了一下 吐槽跨设备同步难搞 然后被人种草了Obsidian 这几天使用下来感觉确实比logseq好用多了 第三方插件同步虽然有点冲突但大体上还好 现在考虑怎么去合理规划tag以及wiznote笔记的迁移 虽说感
  • 刷脸支付机会是留给敢迈出第一步的人

    从支付宝推出余额宝 花呗等功能大幅培养用户理财习惯 到微信支付通过微信红包打通朋友圈 微信支付和支付宝的擂台之战从未平息 面对10亿交易笔数到20亿的跨越 较量已经从扫码支付延伸至了各式各样的甚至难啃的场景 比如停车场无感支付 线下的刷脸支
  • Docker笔记(精简版)

    文章目录 初始Docker 学习背景 Docker解决依赖兼容问题 Docker解决操作系统环境差异 Docker架构 镜像和容器 DockerHub Docker架构 安装Docker 卸载 可选 安装Docker 启动docker 配置
  • VS静态编译C/C++解决程序丢失 VCRUNTIME140.dll

    VS静态编译C C 解决程序丢失 VCRUNTIME140 dll1VS静态编译C C 解决程序丢失 VCRUNTIME140 dll2VS静态编译C C 解决程序丢失 VCRUNTIME140 dll3VS静态编译C C 解决程序丢失 V
  • 【C++ 并发与多线程】std::thread类-为共享数据加锁 2

    正交 消除无关事务之间的影响 力求高内聚低耦合 死锁的概念略去不说 死锁有可能发生在使用多个互斥量的场景下 也可能存在没有使用互斥量的场景 两个线程都在等待对方释放互斥量 两个线程都调用了对方的join 函数 为了解决两个线程都在等待对方释
  • 实施前端微服务化的六七种方式

    微前端架构是一种类似于微服务的架构 它将微服务的理念应用于浏览器端 即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用 由此带来的变化是 这些前端应用可以独立运行 独立开发 独立部署 以及 它们应该可以在共享组件的同时进
  • 记一次Nginx代理Mysql服务的经历

    背景 根据组长背景描述 具备以下前提 1 Mysql服务器为 某A云厂商的RDS SAAS服务 但是不开通外网服务 2 EC2 服务器一台 某A云厂商LaaS服务 也不开通外网 3 阿里云服务器一台 这台服务器有服务需要连接Mysql服务
  • 多列索引

    单列索引与多列索引 索引可以是单列索引 也可以是多列索引 下面我们通过具体的例子来说明这两种索引的区别 假设有这样一个people表 CREATE TABLE people peopleid SMALLINT NOT NULL AUTO I
  • swiper实现无限滚动轮播、左右切换

    废话不多说 直接上代码 const mySwiper ref
  • 经典C语言程序设计100例,部分有个人注解

    经典C语言程序设计100例 程序1 题目 有1 2 3 4个数字 能组成多少个互不相同且无重复数字的三位数 都是多少 1 程序分析 可填在百位 十位 个位的数字都是1 2 3 4 组成所有的排列后再去 掉不满足条件的排列 当然这里的去掉并不
  • QT之读取文本文件中的GPS数据,并解析出经纬度

    include
  • Win10以管理员身份运行CMD命令提示符的四种方法

    方法一 1 我们可以在Windows10系统的开始菜单上 单击鼠标右键 这时候出现的菜单中 我们选择命令提示符 管理员 点击打开这样即可 方法二 1 点击开始菜单 然后界面中我们这里选择所有应用打开进入 如图所示 2 所有应用中 我们在Wi
  • QT中的库类

    目录 QFile详解 文件如果不存在则创建 判断文件是否存在 获得文件的各种详细信息 读写文件 1 QFile文件如果不存在则创建的方法 2 QFileInfo的方法获得文件的各种详细信息 3 QFile读写文件的内容 QTextStrea
  • redis集群拓扑结构自动更新:使用Lettuce连接Cluster集群实例时异常处理

    问题 使用lettuce连接Cluster集群实例 实例执行规格变更后 分片数有变化时 部分槽位 Slot 会迁移到新分片上 当客户端连接到新分片时会出现以下异常问题 java lang IllegalArgumentException C