Help Center > > Best Practices> Implementing Distributed Locks

Implementing Distributed Locks

Updated at: Mar 25, 2019 18:08

The best practice for HUAWEI CLOUD Distributed Cache Service (DCS) guides you through implementation of distributed locks.

Scenario

Locks are used in many Internet scenarios (such as commodities spike and forum posting) to implement sequential access control on certain resources. If application services are deployed in clusters, locks need to be applied to distributed applications. In this case, the locks are known as distributed locks.

Currently, distributed locks are implemented in three ways: disk database, cache database, and Zookeeper.

Distributed locks can be implemented using Redis cache instances of DCS. The advantages are as follows:

  • Simple lock operation: Locks can be acquired and released by using simple commands such as SET, GET, and DEL.
  • Excellent performance: The read/write operations of cache data take precedence over those of the disk database and Zookeeper.
  • High reliability: DCS supports both master/standby and cluster instances, preventing single points of failure.

Example Code for Implementation with Locks

The following code shows only how DCS implements access control using locks. During actual technical implementation, deadlock and lock check also need to be considered.

package dcsDemo01; 
 
import java.util.UUID; 
 
import redis.clients.jedis.Jedis; 
 
public class DistributedLock { 
    private final String host = "192.168.0.220"; 
    private final int port = 6379; 
 
    private static final String SUCCESS = "OK"; 
    private static final String SET_IF_NOT_EXIST = "NX"; 
    private static final String EXPIRE_TIME = "PX"; 
 
    public  DistributedLock(){} 
 
    /* 
     * @param lockName      Lock name 
     * @param timeout       Timeout value for acquiring locks 
     * @param lockTimeout   Validity period of locks 
     * @return              Lock ID 
     */ 
    public String getLockWithTimeout(String lockName, long timeout, long lockTimeout) { 
        String ret = null; 
        Jedis jedisClient = new Jedis(host, port); 
 
        try { 
            String authMsg = jedisClient.auth("Demo@123"); 
            if (!SUCCESS.equals(authMsg)) { 
                System.out.println("AUTH FAILED: " + authMsg); 
            } 
 
            String identifier = UUID.randomUUID().toString(); 
            String lockKey = "DLock:" + lockName; 
            long end = System.currentTimeMillis() + timeout; 
 
            while(System.currentTimeMillis() < end) { 
                String result = jedisClient.set(lockKey, identifier, SET_IF_NOT_EXIST, EXPIRE_TIME, lockTimeout); 
                if(SUCCESS.equals(result)) { 
                    ret = identifier; 
                    break; 
                } 
 
                try { 
                    Thread.sleep(2); 
                } catch (InterruptedException e) { 
                    Thread.currentThread().interrupt(); 
                } 
            } 
        } 
        catch (Exception e) { 
            e.printStackTrace(); 
        }finally { 
            jedisClient.quit(); 
            jedisClient.close(); 
        } 
 
        return ret; 
    } 
 
    /* 
     * @param lockName        Lock name 
     * @param identifier    Lock ID 
     */ 
    public void releaseLock(String lockName, String identifier) { 
        Jedis jedisClient = new Jedis(host, port); 
 
        try { 
            String authMsg = jedisClient.auth("Demo@123"); 
            if (!SUCCESS.equals(authMsg)) { 
                System.out.println("AUTH FAILED: " + authMsg); 
            } 
 
            String lockKey = "DLock:" + lockName; 
            if(identifier.equals(jedisClient.get(lockKey))) { 
                jedisClient.del(lockKey); 
            } 
        } 
        catch (Exception e) { 
            e.printStackTrace(); 
        }finally { 
            jedisClient.quit(); 
            jedisClient.close(); 
        } 
    } 
}

Test Code

Assume that 20 threads are used to seckill ten Huawei Mate 10 mobile phones.

package dcsDemo01; 
import java.util.UUID; 
 
public class CaseTest { 
    public static void main(String[] args) { 
        ServiceOrder service = new ServiceOrder(); 
        for (int i = 0; i < 20; i++) { 
            ThreadBuy client = new ThreadBuy(service); 
            client.start(); 
        } 
    } 
} 
 
class ServiceOrder { 
    private final int MAX = 10; 
 
    DistributedLock DLock = new DistributedLock(); 
 
    int n = 10; 
 
    public void handleOder() { 
        String userName = UUID.randomUUID().toString().substring(0,8) + Thread.currentThread().getName(); 
        String identifier = DLock.getLockWithTimeout("Huawei Mate 10", 10000, 2000); 
        System.out.println("Processing order for user " + userName + ""); 
        if(n > 0) { 
            int num = MAX - n + 1; 
            System.out.println("User " + userName + " is allocated number " + num + " mobile phone. Number of mobile phones left: " + (--n) + ".); 
        }else { 
            System.out.println("User " + userName + " order failed. All mobile phones sold out."); 
        } 
        DLock.releaseLock("Huawei Mate 10", identifier); 
    } 
} 
 
class ThreadBuy extends Thread { 
    private ServiceOrder service; 
 
    public ThreadBuy(ServiceOrder service) { 
        this.service = service; 
    } 
 
    @Override 
    public void run() { 
        service.handleOder(); 
    } 
}

Operation Guidance

  1. Prepare an Elastic Cloud Server (ECS) that runs a Windows OS.
  2. Install JDK1.8 (or later) and Eclipse on the ECS, and download the Jedis client. (Click to download the jar package.)
  3. Purchase DCS instances on the management console. Ensure that you select the same VPC, subnet, and security group as the ECS.
  4. Run Eclipse on the ECS, and create a Java project. Then, create a distributed lock implementation class DistributedLock.java and a test class CaseTest.java for the example code, and reference the Jedis client as a library to the project.
  5. Configure a connection address, port number, and connection password for the DCS instances in the example code file. Note that you need to configure a password in both getLockWithTimeout and releaseLock.
  6. Compile and run the code.

Operation Result

Compile and run the preceding example code. The operation result is as follows:

Processing order for user eee56fb7Thread-16 
User eee56fb7Thread-16 is allocated number 1 mobile phone. Number of mobile phones left: 9. 
Processing order for user d6521816Thread-2 
User d6521816Thread-2 is allocated number 2 mobile phone. Number of mobile phones left: 8. 
Processing order for user d7b3b983Thread-19 
User d7b3b983Thread-19 is allocated number 3 mobile phone. Number of mobile phones left: 7. 
Processing order for user 36a6b97aThread-15 
User 36a6b97aThread-15 is allocated number 4 mobile phone. Number of mobile phones left: 6. 
Processing order for user 9a973456Thread-1 
User 9a973456Thread-1 is allocated number 5 mobile phone. Number of mobile phones left: 5. 
Processing order for user 03f1de9aThread-14 
User 03f1de9aThread-14 is allocated number 6 mobile phone. Number of mobile phones left: 4. 
Processing order for user 2c315ee6Thread-11 
User 2c315ee6Thread-11 is allocated number 7 mobile phone. Number of mobile phones left: 3. 
Processing order for user 2b03b7c0Thread-12 
User 2b03b7c0Thread-12 is allocated number 8 mobile phone. Number of mobile phones left: 2. 
Processing order for user 75f25749Thread-0 
User 75f25749Thread-0 is allocated number 9 mobile phone. Number of mobile phones left: 1. 
Processing order for user 26c71db5Thread-18 
User 26c71db5Thread-18 is allocated number 10 mobile phone. Number of mobile phones left: 0. 
Processing order for user c32654dbThread-17 
User c32654dbThread-17 order failed. All mobile phones sold out. 
Processing order for user df94370aThread-7 
User df94370aThread-7 order failed. All mobile phones sold out. 
Processing order for user 0af94cddThread-5 
User 0af94cddThread-5 order failed. All mobile phones sold out. 
Processing order for user e52428a4Thread-13 
User e52428a4Thread-13 order failed. All mobile phones sold out. 
Processing order for user 46f91208Thread-10 
User 46f91208Thread-10 order failed. All mobile phones sold out. 
Processing order for user e0ca87bbThread-9 
User e0ca87bbThread-9 order failed. All mobile phones sold out. 
Processing order for user f385af9aThread-8 
User f385af9aThread-8 order failed. All mobile phones sold out. 
Processing order for user 46c5f498Thread-6 
User 46c5f498Thread-6 order failed. All mobile phones sold out. 
Processing order for user 935e0f50Thread-3 
User 935e0f50Thread-3 order failed. All mobile phones sold out. 
Processing order for user d3eaae29Thread-4 
User d3eaae29Thread-4 order failed. All mobile phones sold out.

Example Code for Implementation Without Locks

If the lock code is commented out, locks are not applied and user orders are not processed sequentially.

//The lock code is commented out in the test class: 
public void handleOder() { 
    String userName = UUID.randomUUID().toString().substring(0,8) + Thread.currentThread().getName(); 
    //Lock code 
    //String identifier = DLock.getLockWithTimeout("Huawei Mate 10", 10000, 2000); 
    System.out.println("Processing order for user " + userName + ""); 
    if(n > 0) { 
        int num = MAX - n + 1; 
        System.out.println("User "+ userName + " is allocated number " + num + " mobile phone. Number of mobile phones left: " + (--n) + ""); 
    }else { 
        System.out.println("User "+ userName + " order failed. All mobile phones sold out."); 
    } 
    //Lock code 
    //DLock.releaseLock("Huawei Mate 10", identifier); 
}

The following operation result shows that the order processing is unsequential after the lock code is commented out.

Processing order for user e04934ddThread-5 
Processing order for user a4554180Thread-0 
User a4554180Thread-0 is allocated number 2 mobile phone. Number of mobile phones left: 8. 
Processing order for user b58eb811Thread-10 
User b58eb811Thread-10 is allocated number 3 mobile phone. Number of mobile phones left: 7. 
Processing order for user e8391c0eThread-19 
Processing order for user 21fd133aThread-13 
Processing order for user 1dd04ff4Thread-6 
User 1dd04ff4Thread-6 is allocated number 6 mobile phone. Number of mobile phones left: 4. 
Processing order for user e5977112Thread-3 
Processing order for user 4d7a8a2bThread-4 
User e5977112Thread-3 is allocated number 7 mobile phone. Number of mobile phones left: 3. 
Processing order for user 18967410Thread-15 
User 18967410Thread-15 is allocated number 9 mobile phone. Number of mobile phones left: 1. 
Processing order for user e4f51568Thread-14 
User 21fd133aThread-13 is allocated number 5 mobile phone. Number of mobile phones left: 5. 
User e8391c0eThread-19 is allocated number 4 mobile phone. Number of mobile phones left: 6. 
Processing order for user d895d3f1Thread-12 
User d895d3f1Thread-12 order failed. All mobile phones sold out. 
Processing order for user 7b8d2526Thread-11 
User 7b8d2526Thread-11 order failed. All mobile phones sold out. 
Processing order for user d7ca1779Thread-8 
User d7ca1779Thread-8 order failed. All mobile phones sold out. 
Processing order for user 74fca0ecThread-1 
User 74fca0ecThread-1 order failed. All mobile phones sold out. 
User e04934ddThread-5 is allocated number 1 mobile phone. Number of mobile phones left: 9. 
User e4f51568Thread-14 is allocated number 10 mobile phone. Number of mobile phones left: 0. 
Processing order for user aae76a83Thread-7 
User aae76a83Thread-7 order failed. All mobile phones sold out. 
Processing order for user c638d2cfThread-2 
User c638d2cfThread-2 order failed. All mobile phones sold out. 
Processing order for user 2de29a4eThread-17 
User 2de29a4eThread-17 order failed. All mobile phones sold out. 
Processing order for user 40a46ba0Thread-18 
User 40a46ba0Thread-18 order failed. All mobile phones sold out. 
Processing order for user 211fd9c7Thread-9 
User 211fd9c7Thread-9 order failed. All mobile phones sold out. 
Processing order for user 911b83fcThread-16 
User 911b83fcThread-16 order failed. All mobile phones sold out. 
User 4d7a8a2bThread-4 is allocated number 8 mobile phone. Number of mobile phones left: 2. 

Did you find this page helpful?

Submit successfully!

Thank you for your feedback. Your feedback helps make our documentation better.

Failed to submit the feedback. Please try again later.

Which of the following issues have you encountered?







Please complete at least one feedback item.

Content most length 200 character

Content is empty.

OK Cancel