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

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!

主站蜘蛛池模板: 镇赉县| 红安县| 三穗县| 井研县| 石家庄市| 于都县| 通城县| 万全县| 苍南县| 平舆县| 措勤县| 望奎县| 长丰县| 岚皋县| 静乐县| 保德县| 衡水市| 启东市| 永平县| 民丰县| 三都| 崇左市| 兴义市| 秦安县| 金塔县| 惠东县| 延津县| 孟州市| 唐海县| 普兰店市| 磴口县| 同德县| 延津县| 清河县| 广汉市| 金乡县| 镇巴县| 邛崃市| 广饶县| 刚察县| 新建县|