이 글은 Redis를 사용하여 분산 잠금을 구현하는 방법에 대한 자세한 설명(코드 예제)을 제공합니다. 필요한 친구들이 참고할 수 있기를 바랍니다.
분산 잠금 구현을 위해 Redis를 선택한 이유
Redis는 성능이 뛰어납니다
Redis 명령이 이를 더 잘 지원하고 구현하기가 더 편리합니다# 🎜 🎜#
명령 사용 소개
SETNXSETNX 키 값
if 그리고 다음과 같은 경우에만 키가 없으면 키 값을 사용하여 문자열을 설정하고 1을 반환합니다. 키가 있으면 아무 작업도 수행하지 않고 0을 반환합니다.expireexpire key timeout
키 시간 제한을 초 단위로 설정하세요. 교착 상태를 방지하기 위해 이 시간이 지나면 잠금이 자동으로 해제됩니다.deletedelete key
delete key구현
은 jedis를 사용하여 Redis에 연결합니다.구현 아이디어
잠금을 획득할 때 setnx를 사용하여 잠그고 만료 명령을 사용하여 잠금에 제한 시간을 추가합니다. 이 시간을 초과하면 잠금이 자동으로 해제되며, 잠금 값은 잠금 해제 시기를 결정하는 데 사용되는 무작위로 생성된 UUID입니다. 락 획득 시, 획득 제한 시간도 설정되어 있으며, 이 시간을 초과할 경우 락 획득이 포기됩니다. 잠금을 해제할 때 UUID를 사용하여 잠금인지 확인합니다. 잠금인 경우 삭제를 실행하여 잠금을 해제합니다. 분산 잠금의 핵심 코드는 다음과 같습니다.import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.Transaction; import redis.clients.jedis.exceptions.JedisException; import java.util.List; import java.util.UUID; public class DistributedLock { private final JedisPool jedisPool; public DistributedLock(JedisPool jedisPool) { this.jedisPool = jedisPool; } /** * 加锁 * @param locaName 锁的key * @param acquireTimeout 获取超时时间 * @param timeout 锁的超时时间 * @return 锁标识 */ public String lockWithTimeout(String locaName, long acquireTimeout, long timeout) { Jedis conn = null; String retIdentifier = null; try { // 获取连接 conn = jedisPool.getResource(); // 随机生成一个value String identifier = UUID.randomUUID().toString(); // 锁名,即key值 String lockKey = "lock:" + locaName; // 超时时间,上锁后超过此时间则自动释放锁 int lockExpire = (int)(timeout / 1000); // 获取锁的超时时间,超过这个时间则放弃获取锁 long end = System.currentTimeMillis() + acquireTimeout; while (System.currentTimeMillis() results = transaction.exec(); if (results == null) { continue; } retFlag = true; } conn.unwatch(); break; } } catch (JedisException e) { e.printStackTrace(); } finally { if (conn != null) { conn.close(); } } return retFlag; } }
예시에서는 상품의 반짝 세일을 시뮬레이션하기 위해 50개의 스레드가 사용되었으며, 상품을 줄이기 위해 -- 연산자를 사용하여 결과의 순서를 보면 잠겨 있는지를 알 수 있습니다. 상태.
import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class Service { private static JedisPool pool = null; static { JedisPoolConfig config = new JedisPoolConfig(); // 设置最大连接数 config.setMaxTotal(200); // 设置最大空闲数 config.setMaxIdle(8); // 设置最大等待时间 config.setMaxWaitMillis(1000 * 100); // 在borrow一个jedis实例时,是否需要验证,若为true,则所有jedis实例均是可用的 config.setTestOnBorrow(true); pool = new JedisPool(config, "127.0.0.1", 6379, 3000); } DistributedLock lock = new DistributedLock(pool); int n = 500; public void seckill() { // 返回锁的value值,供释放锁时候进行判断 String indentifier = lock.lockWithTimeout("resource", 5000, 1000); System.out.println(Thread.currentThread().getName() + "获得了锁"); System.out.println(--n); lock.releaseLock("resource", indentifier); } }
public class ThreadA extends Thread { private Service service; public ThreadA(Service service) { this.service = service; } @Override public void run() { service.seckill(); } } public class Test { public static void main(String[] args) { Service service = new Service(); for (int i = 0; i 결과는 다음과 같으며, 결과는 순서대로입니다. <p></p><p style="text-align: center;"><span class="img-wrap"><img src="https://img.php.cn//upload/image/211/984/157/1540025904941327.png" title="1540025904941327.png" alt="Redis를 사용하여 분산 잠금을 구현하는 방법에 대한 자세한 설명(코드 예)"></span></p>자물쇠를 사용하는 부분을 댓글로 달아주시면<p></p><pre class="brush:php;toolbar:false">public void seckill() { // 返回锁的value值,供释放锁时候进行判断 //String indentifier = lock.lockWithTimeout("resource", 5000, 1000); System.out.println(Thread.currentThread().getName() + "获得了锁"); System.out.println(--n); //lock.releaseLock("resource", indentifier); }
분산 환경에서는 특정 리소스를 스냅하는 등 리소스를 잠그는 것이 때로는 중요합니다. 이번에는 분산 잠금을 사용하여 리소스를 효과적으로 제어할 수 있습니다. 물론 특정 용도에서는 타임아웃 시간 선택, 잠금 획득 시간 선택 등 동시성 양에 큰 영향을 미치는 많은 요소를 고려해야 합니다. 위에 구현된 잠금은 단순한 구현일 뿐이며 대부분은 아이디어입니다. [사실 redis를 사용하여 구현한 분산 잠금보다 Zookeeper를 사용하는 신뢰성이 더 높지만, 그에 비해 성능은 Redis가 더 좋습니다. ]
위 내용은 Redis를 사용하여 분산 잠금을 구현하는 방법에 대한 자세한 설명(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!