>  기사  >  Java  >  분산 잠금 구현을 위한 Spring Cloud 마이크로서비스 실습

분산 잠금 구현을 위한 Spring Cloud 마이크로서비스 실습

王林
王林원래의
2023-06-22 23:28:38775검색

마이크로서비스 아키텍처의 인기로 인해 점점 더 많은 엔터프라이즈 개발 팀이 Spring Cloud를 사용하여 자체 마이크로서비스 시스템을 구축하기 시작했습니다. 분산 환경에서 분산 잠금을 구현하는 것은 중요한 기술적 과제입니다. 이 기사에서는 Spring Cloud 프레임워크에서 분산 잠금의 마이크로서비스 방식을 구현하는 방법을 소개합니다.

먼저 분산 잠금이 무엇인지 이해해야 합니다. 분산 잠금은 공유 리소스에 대한 액세스를 보호하는 데 사용되는 기술로, 분산 환경에서 여러 노드가 동시에 동일한 리소스를 수정하거나 액세스하지 못하도록 보장할 수 있습니다. 마이크로서비스 시스템에서 분산 잠금은 공유 리소스의 읽기 및 쓰기를 보호하고 리소스 경쟁과 데이터 불일치를 방지할 수 있습니다.

다음으로 Redis를 사용하여 분산 잠금을 구현하는 솔루션을 소개하겠습니다. Redis는 분산 잠금을 지원하고 Spring Cloud 프레임워크와 원활하게 통합될 수 있는 인기 있는 인메모리 데이터베이스입니다.

먼저 Spring Boot 애플리케이션에 Redis의 종속성을 추가해야 합니다. Gradle에 다음 종속성을 추가합니다.

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'

Maven에 다음 종속성을 추가합니다.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Redis 연결을 구성하려면 애플리케이션에 다음 코드를 추가합니다.

@Configuration
public class RedisConfig {

  @Bean
  JedisConnectionFactory jedisConnectionFactory() {
      RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
      redisStandaloneConfiguration.setHostName("redis");
      redisStandaloneConfiguration.setPort(6379);
      return new JedisConnectionFactory(redisStandaloneConfiguration);
  }

  @Bean
  public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
      RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
      redisTemplate.setConnectionFactory(redisConnectionFactory);
      redisTemplate.setDefaultSerializer(new StringRedisSerializer());
      redisTemplate.setEnableTransactionSupport(true);
      redisTemplate.afterPropertiesSet();
      return redisTemplate;
  }
}

다음으로 분산 잠금을 얻기 위한 메서드를 구현해야 합니다. . 이 방법은 분산 환경에서 오직 하나의 노드만이 동시에 잠금을 얻을 수 있도록 보장해야 합니다. 다음은 간단한 구현입니다.

@Service
public class DistributedLockService {

    @Autowired
    private RedisTemplate redisTemplate;

    public boolean acquireLock(String lockKey, String requestId, int expireTime) {

        String result = (String) redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                JedisCommands commands = (JedisCommands) connection.getNativeConnection();
                return commands.set(lockKey, requestId, "NX", "PX", expireTime);
            }
        });

        return result != null && result.equals("OK");
    }

    public boolean releaseLock(String lockKey, String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Boolean result = (Boolean) redisTemplate.execute(new RedisCallback<Boolean>() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                Object nativeConnection = connection.getNativeConnection();
                Long execute = (Long) ((Jedis) nativeConnection).eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
                return execute.equals(1L);
            }
        });
        return result;
    }
}

위 코드에서 redisTemplate의 실행 메소드를 통해 Redis set 명령을 실행하여 키-값 쌍을 설정합니다. NX 매개변수는 키가 존재하지 않는 경우에만 설정된다는 의미입니다. 두 스레드가 동시에 잠금 상황을 얻는 것을 방지합니다. PX 매개변수는 설정된 키의 만료 시간을 나타냅니다. 반환 결과는 OK이며 잠금이 성공적으로 획득되었음을 나타냅니다. 잠금을 해제할 때 Redis의 Lua 스크립트 구현을 사용하여 잠금을 소유한 스레드만 잠금을 해제할 수 있는지 확인하세요.

마지막으로 마이크로서비스에서는 분산 잠금을 사용해야 합니다. 예를 들어, 리소스 액세스를 보호해야 하는 마이크로서비스 엔드포인트가 있다고 가정하면 Spring MVC 컨트롤러에서 DistributedLockService를 사용하여 동시에 하나의 요청만 리소스에 액세스할 수 있도록 분산 잠금을 얻을 수 있습니다.

@RestController
public class ResourceController {

  private static final String LOCK_KEY = "lock";
  private static final String LOCK_REQUEST_ID = UUID.randomUUID().toString();
  private static final int EXPIRE_TIME = 5000;

  @Autowired
  private DistributedLockService distributedLockService;

  @Autowired
  private ResourceService resourceService;

  @RequestMapping("/resource")
  public ResponseEntity<String> accessResource() {

      boolean lockAcquired = distributedLockService.acquireLock(LOCK_KEY, LOCK_REQUEST_ID, EXPIRE_TIME);

      if (lockAcquired) {
          try {
              // 访问资源
              String result = resourceService.accessResource();
              return ResponseEntity.ok(result);
          } finally {
              distributedLockService.releaseLock(LOCK_KEY, LOCK_REQUEST_ID);
          }
      } else {
          return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("Resource is busy, please try again later.");
      }
  }
}

위 코드는 DistributedLockService를 통해 잠금을 획득하고, 잠금을 획득한 후 리소스에 액세스하고, 리소스에 액세스한 후 잠금을 해제하여 동시에 여러 요청이 리소스에 액세스하는 문제를 피합니다.

위 예에서는 Spring Cloud 마이크로서비스에 분산 잠금 체계를 구현했습니다. 이 솔루션은 공유 리소스에 대한 액세스를 보호하고 시스템 데이터의 정확성과 일관성을 보장할 수 있습니다. 실제 사용에서는 특정 비즈니스 시나리오 및 요구 사항에 따라 분산 잠금 구현을 조정하고 최적화할 수 있습니다.

간단히 말하면 분산 잠금은 분산 시스템을 구현하는 데 매우 중요한 부분이며 시스템 데이터의 정확성과 일관성을 보장할 수 있습니다. Spring Cloud와 Redis의 조합은 분산 잠금 기능을 잘 구현할 수 있습니다. 이 글의 소개를 통해 모든 사람이 분산 잠금 기술을 이해하고 적용하는 데 조금이나마 도움이 되기를 바랍니다.

위 내용은 분산 잠금 구현을 위한 Spring Cloud 마이크로서비스 실습의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.