官术网_书友最值得收藏!

Distributed locking

When building a broad, horizontally scaled application, one aspect that we tend to lose is the ability to restrict and prevent concurrent activity across the whole application. Within a single JVM, we use a synchronized lock to guard a section of functionality from a concurrent execution. Once we move away from a single JVM, this problem becomes a much bigger issue. Traditional approaches would leverage a transactional database to provide a system for locking in the form of a table rowlock or a transactional state. However, this approach presents us with a single point of failure and contention issues when scaling up our application.

Hazelcast offers a distributed locking facility, allowing us to attempt acquiring a cluster-wide named lock, and guard the functionality behind it. If we can create an example class LockingExample, we can demonstrate this ability, as follows:

public class LockingExample {
  public static void main(String[] args) throws Exception {
    HazelcastInstance hz = Hazelcast.newHazelcastInstance();

    Lock lock = hz.getLock("theTime");

    while (true) {
      if (lock.tryLock(30, TimeUnit.SECONDS)) {
        try {
          while (true) {
            System.err.println(new Date());
            Thread.sleep(1000);
          }
        }
        finally {
          lock.unlock();
        }
      }
    }
  }
}

When considering the preceding code, we are continuously attempting to acquire the theTime lock. Should we be successful in acquiring the lock, we shall continuously start printing out the time every second. If we run the class once, we will see the behavior as described:

Members [1] {
 Member [127.0.0.1]:5701 this
}

Thu Jan 01 00:00:00 UTC 2015
Thu Jan 01 00:00:01 UTC 2015
Thu Jan 01 00:00:02 UTC 2015
Thu Jan 01 00:00:03 UTC 2015

However, if we start running the example multiple times, we enable the resilience of the locked section in that, the multiple nodes are all continuously trying to enter the block of code but are prevented by the acquired lock of another running instance. This is where the locking capability provided by Hazelcast shows its strength. If we were to start killing off nodes, especially the ones currently holding the lock, we fail-safe. By killing the nodes that are not holding the lock, the correct behavior is still enforced. However, if we kill off the node that is currently holding the lock, it will be automatically released, as the owner is now dead. At this point, another node can now acquire the lock and take over the responsibility of telling us the time.

Using this capability, we have provided the application with the ability to have a resilient, but exclusive, execution task that exists within the cluster. Where this task actually occurs isn't particularly controllable, but assuming that the nodes are present, it is guaranteed to run somewhere, but only once.

Tactical locking

In addition to a single, blunt gatekeeper locking where we effectively prevent concurrent execution across the entire cluster for a specific type of activity, we might want to lock on a more specific context. Rather than using a Lock object, IMap provides us with entry locking capabilities. Using this, we can acquire a mutex on a specific entry, enabling the ability to prevent concurrent modifications on a targeted piece of data, as follows:

public class MapLockingExample {
  public static void main(String[] args) {
    HazelcastInstance hz = Hazelcast.newHazelcastInstance();

    IMap<String, Date> arrivals = hz.getMap("arrivals");

    if (arrivals.tryLock("London")) {
      try {
        arrivals.put("London", new Date());
      }
      finally {
        arrivals.unlock("London");
      }
    }
    System.err.println("London: " + arrivals.get("London"));
  }
}

While we have explicitly acquired, processed, and reliably released the lock, this gives us an absolute control over the amount of blocking that we might be introducing into our application. If used wisely, this is a very powerful tool.

Note

It is probably always the best choice to use locks with a defined time, as without this, the threads will block indefinitely!

主站蜘蛛池模板: 富蕴县| 闽清县| 舞钢市| 玉龙| 安达市| 油尖旺区| 新晃| 河东区| 旬阳县| 湖南省| 左云县| 巴林右旗| 敖汉旗| 昌平区| 平果县| 靖安县| 深水埗区| 岑溪市| 萨嘎县| 逊克县| 彩票| 雅安市| 西盟| 大同市| 通许县| 拉萨市| 海城市| 缙云县| 泌阳县| 长武县| 大荔县| 余庆县| 迁西县| 葵青区| 西乌珠穆沁旗| 镇远县| 平塘县| 灌阳县| 来安县| 满洲里市| 达日县|