lettuce中无法获取锁异常

问题描述 投票:0回答:2

我们最近在生产服务中从 jedis 转向使用生菜。然而,我们在创建 Redis 分布式锁时遇到了障碍

我们正在使用 aws elasticache 的非集群设置,其中一个主服务器和 2 个读取 repilcas

配置:

Spring 启动:2.2.5

spring-boot-starter-data-redis:2.2.5

spring-data-redis:2.2.5

弹簧集成-redis:5.2.4

redis:5.0.6

@Bean
    public LettuceConnectionFactory redisConnectionFactory() {

        GenericObjectPoolConfig poolingConfig = new GenericObjectPoolConfig();
        poolingConfig.setMaxIdle(Integer.valueOf(maxConnections));
        poolingConfig.setMaxTotal(Integer.valueOf(maxIdleConnections));
        poolingConfig.setMinIdle(Integer.valueOf(minIdleConnections));
        poolingConfig.setMaxWaitMillis(-1);
        
        final SocketOptions socketOptions = SocketOptions.builder().connectTimeout(Duration.ofSeconds(10)).build();
        final ClientOptions clientOptions = ClientOptions.builder().socketOptions(socketOptions).build();

        LettucePoolingClientConfiguration clientOption = LettucePoolingClientConfiguration.builder()
                .poolConfig(poolingConfig).readFrom(ReadFrom.REPLICA_PREFERRED)
                .commandTimeout(Duration.ofMillis(Long.valueOf(commandTimeout)))
                .clientOptions(clientOptions).useSsl().build();

        RedisStaticMasterReplicaConfiguration redisStaticMasterReplicaConfiguration = new RedisStaticMasterReplicaConfiguration(
                primaryEndPoint, Integer.valueOf(port));
        redisStaticMasterReplicaConfiguration.addNode(readerEndPoint, Integer.valueOf(port));
        redisStaticMasterReplicaConfiguration.setPassword(password);

        /*
         * LettuceClientConfiguration clientConfig = LettuceClientConfiguration
         * .builder() .useSsl()
         * 
         * .readFrom(new ReadFrom() {
         * 
         * @Override public List<RedisNodeDescription> select(Nodes nodes) {
         * List<RedisNodeDescription> allNodes = nodes.getNodes(); int ind =
         * Math.abs(index.incrementAndGet() % allNodes.size()); RedisNodeDescription
         * selected = allNodes.get(ind);
         * //logger.info("Selected random node {} with uri {}", ind, selected.getUri());
         * List<RedisNodeDescription> remaining = IntStream.range(0, allNodes.size())
         * .filter(i -> i != ind) .mapToObj(allNodes::get).collect(Collectors.toList());
         * return Stream.concat( Stream.of(selected), remaining.stream()
         * ).collect(Collectors.toList()); } }) .build();
         */
        return new LettuceConnectionFactory(redisStaticMasterReplicaConfiguration, clientOption);
    }
    
    @Bean
    public StringRedisTemplate stringRedisTemplate() {
        return new StringRedisTemplate(redisConnectionFactory());
    }

上锁服务

@Service
public class RedisLockService {
    
    @Autowired
    RedisConnectionFactory redisConnectionFactory;
    
            
    private static final Logger LOGGER = LoggerFactory.getLogger(RedisLockService.class);
    
    public Lock obtainLock(String registryKey,String redisKey,Long lockExpiry){
         
        try{
             RedisLockRegistry registry = new RedisLockRegistry(redisConnectionFactory, registryKey, lockExpiry);
             Lock lock = registry.obtain(redisKey);
             if(lock.tryLock()==false)
             {
                 LOGGER.info("Lock already made");
                 return null;
             }
             else
                 return lock;
            
         }catch (Exception e) {
                LOGGER.warn("Unable to acquire lock: ", e);
                return null;                
         }
     } 

    public void unLock(Lock lock) {
        if(lock!=null)
            lock.unlock();
    }
}

我们在尝试调用obtainLock函数时遇到错误

.RedisSystemException: Error in execution; nested exception is io.lettuce.core.RedisCommandExecutionException: ERR Error running script (call to f_8426c8df41c64d8177dce3ecbbe9146ef3759cd2): @user_script:6: @user_script: 6: -READONLY You can't write against a read only replica.   
    at org.springframework.integration.redis.util.RedisLockRegistry$RedisLock.rethrowAsLockException(RedisLockRegistry.java:224)
    at org.springframework.integration.redis.util.RedisLockRegistry$RedisLock.tryLock(RedisLockRegistry.java:276)
    at org.springframework.integration.redis.util.RedisLockRegistry$RedisLock.tryLock(Re
spring spring-boot redis spring-data-redis lettuce
2个回答
0
投票

需要连接Redis的主读/写节点


0
投票

我们需要连接到master来锁定 使用代码 configBuilder 从 MASTER 读取 LettuceClientConfigurationBuilder configBuilder = LettuceClientConfiguration.builder().readFrom(ReadFrom.MASTER);

if (encryptionEnabled) { // useSsl if encryption enabled.
  configBuilder.useSsl();
}

RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();
clusterConfiguration.clusterNode(redisProperties.getHost(), redisProperties.getPort());
if (StringUtils.hasText(redisProperties.getUsername())) {
  clusterConfiguration.setUsername(redisProperties.getUsername());
}
if (StringUtils.hasText(redisProperties.getPassword())) {
  clusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));
}
return new LettuceConnectionFactory(clusterConfiguration, configBuilder.build());
© www.soinside.com 2019 - 2024. All rights reserved.