Distributed lock-Redisson

  The previous chapter wrote about distributed locks that are simply implemented using Redis, but in fact, the official does not recommend this method. The official recommendation is that we use an algorithm called the Redlock algorithm to achieve better results. And this framework is adapted to many languages, it is more powerful, although it will be a bit more difficult, but I use Java development, of course, use Redisson
Insert picture description here
  Redisson is a Java in-memory data grid (In-Memory Data Grid) based on Redis. Grid). It not only provides a series of distributed Java commonly used objects, but also provides many distributed services. These include (BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service , Scheduler service) Redisson provides the easiest and most convenient way to use Redis. The purpose of Redisson is to promote the separation of concerns from users to Redis, so that users can focus more on processing business logic.
  Next, start using Redisson to
  import the jar package. Redisson, as a framework in the team, needs to import its jar package when using it, first in ordinary projects.

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.14.1</version>
</dependency>

  There are two ways to configure Redisson, one is through program configuration, the other is through configuration file

@Configuration
public class RedissonConfig {
    
    
    /**
     * 将Redisson配置到容器中
     */
    @Bean(destroyMethod = "shutdown")//服务停止后销毁
    public RedissonClient redisson() throws IOException {
    
    
        Config config = new Config();
        //集群模式
//        config.useClusterServers().addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001");
        //单节点模式
        config.useSingleServer().setAddress("redis://192.168.0.109:6379").setPassword("没密码可以不配置此项");
        return Redisson.create(config);
    }
}

  Then you test uses a distributed lock on the
reentrant lock
  if there are A, B two methods, A method to call B, A and B method should be locked and added that the same lock, if it is re-entrant Yes, when method A is executed to call method B, method A has been locked, and method B detects that method A has been locked and uses this lock directly to execute method B. After execution, A releases the lock. If it is designed to be unavailable For reentrant locks, both A and B need to hold the same lock. When A holds the lock, B can only execute after A releases the lock, and A waits for B to finish executing before releasing the lock, which causes a deadlock, so All locks should be designed as reentrant locks to avoid deadlock problems

@Autowired
private RedissonClient redissonClient;
public void redsissonDemo() {
    
    
    //获取一把锁,只要锁名字一样就是同一把锁
    RLock lock = redissonClient.getLock("lock");
    // 加锁
    /*
     * 方式一 默认过期时间
     * 加锁方法有两个特点
     * 1. 看门狗机制,在业务逻辑执行期间自动给锁续期
     * 2. 默认锁30S后过期,即使业务宕机没有解锁
     */
    lock.lock();//阻塞式等待
    /*
     * 方式二 指定过期时间
     * 通过源码,此方法传递的超时时间,超时后就删除锁,不会自动续期
     */
    lock.lock(10,TimeUnit.SECONDS);

    try {
    
    
        System.out.println("执行业务略及");
    } finally {
    
    
        // 解锁
        lock.unlock();
    }
}

Read-write locks
  Read-write locks are divided into read locks and write locks. These two appear in pairs. For example, when a service is modifying a data, and other services need to read this data, it must wait for the write lock to be released before reading If both are read, they will not affect each other, that is, when the write lock exists, the read lock can only wait. The advantage of adding a read-write lock is that the data read must be the latest

@Autowired
private RedissonClient redissonClient;
public void writeLock() {
    
    
    //读写锁
    RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
    //加写锁
    RLock rLock = lock.writeLock();
    rLock.lock();
    try {
    
    
        System.out.println("执行修改数据");
    } finally {
    
    
        rLock.unlock();
    }
}
public void readLock() {
    
    
    //读写锁
    RReadWriteLock lock = redissonClient.getReadWriteLock("rw-lock");
    RLock rLock = lock.readLock();
    rLock.lock();
    try {
    
    
        System.out.println("执行读取数据");
    } finally {
    
    
        rLock.unlock();
    }
}

Semaphore
  may have such a scenario in our business. At certain moments, we need to limit the current of certain interfaces. You can use semaphores to solve this problem. When each thread executes, first get a semaphore. When the semaphore After all have been obtained, if there are still requests, these requests will be blocked and wait until the semaphore is obtained, of course, it can also be ended early

    public void getSemaphore() throws InterruptedException {
    
    
        RSemaphore sem = redissonClient.getSemaphore("sem");
//        sem.acquire();//获取一个信号量(阻塞式获取)
        boolean b = sem.tryAcquire();//尝试获取信号量
        if (b) {
    
    
            System.out.println("执行业务逻辑");
        }
        //没获取到直接结束
    }

    public void releaseSemaphore() {
    
    
        RSemaphore sem = redissonClient.getSemaphore("sem");
        sem.release();//释放信号量
        System.out.println("执行业务逻辑");
    }

  The above are some of our commonly used locks. Of course, there are not only these few that are officially provided. For detailed documents, please refer to the official document ( Portal )
  . The bottom layer of Redisson is guaranteed by Lua scripts, so all its locks are guaranteed to be atomic, and Based on its watchdog mechanism, Redisson solves the deadlock problem and is simpler and more powerful to use than Redis. It is recommended to use Redisson in the project.

Guess you like

Origin blog.csdn.net/weixin_45481406/article/details/113358432