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

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!

主站蜘蛛池模板: 西丰县| 贺州市| 清水县| 那曲县| 临西县| 景谷| 夏津县| 南宁市| 南投市| 日照市| 封开县| 噶尔县| 漳州市| 新丰县| 肥西县| 合水县| 永福县| 从江县| 东乡县| 麦盖提县| 慈溪市| 吴川市| 通许县| 邢台县| 巨野县| 墨玉县| 济南市| 平南县| 南丰县| 措美县| 遂溪县| 科尔| 乌海市| 太谷县| 凌源市| 民和| 台南市| 专栏| 江城| 马龙县| 仁怀市|