ホームページ  >  記事  >  Java  >  分散ロックを実装するための Spring Cloud マイクロサービスの実践

分散ロックを実装するための Spring Cloud マイクロサービスの実践

王林
王林オリジナル
2023-06-22 23:28:38744ブラウズ

マイクロサービス アーキテクチャの人気に伴い、ますます多くのエンタープライズ開発チームが 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;
  }
}

次に、分散ロックを取得するメソッドを実装する必要があります。この方法では、分散環境で同時に 1 つのノードだけがロックを取得できるようにする必要があります。

@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;
    }
}

上記のコードでは、Redis set コマンドが redisTemplate の実行メソッドを通じて実行され、キーと値のペアが設定されます。NX パラメーターは、次の場合にのみ設定されることを意味します。 2 つのスレッドが同時にロックを取得する状況を避けるためにキーが存在しません。 PX パラメータは、設定されたキーの有効期限を示します。戻り結果は OK で、ロックが正常に取得されたことを示します。ロックを解放するときは、Redis の Lua スクリプト実装を使用して、ロックを所有するスレッドのみがロックを解放できるようにします。

最後に、マイクロサービスで分散ロックを使用する必要があります。たとえば、リソース アクセスを保護する必要があるマイクロサービス エンドポイントがあると仮定すると、Spring MVC コントローラーで DistributedLockService を使用して分散ロックを取得し、同時に 1 つのリクエストのみがリソースにアクセスできるようにすることができます。

@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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。