GemFire CacheWriter中的并发线程

时间:2017-08-24 02:31:05

标签: gemfire spring-data-gemfire

我们目前使用Cassandra作为NoSQL数据库,使用GemFire作为内存数据库。我们一直在使用GemFire CacheWriter在Cassandra中插入记录。我希望您对使用CacheWriter中的Concurrent线程插入/更新记录是否是一个好的工程实践提出反馈。您的意见将不胜感激。

public class GenericWriter<K, V> extends CacheWriterAdapter<K, V> implements Declarable {

    private static Logger log = LoggerFactory.getLogger(GenericWriter.class);

    @Autowired
    private CassandraOperations cassandraOperations;

    ExecutorService executor = null;

    @Override
    public void beforeCreate(EntryEvent<K, V> e) {

    executor = Executors.newSingleThreadExecutor();

        executor.submit(() -> {
            if (eventOperation.equals("CREATE") || eventOperation.equalsIgnoreCase("PUTALL_CREATE")) {
                try {
                    cassandraOperations.insert(e.getNewValue());
                } catch (CassandraConnectionFailureException | CassandraWriteTimeoutException
                        | CassandraInternalException cassException) {
                } catch (Exception ex) {
                    log.error("Exception in GenericCacheWriter->" + ExceptionUtils.getStackTrace(ex));
                    throw ex;
                }
            }
        });
        executor.shutdown();
    }

    @Override
    public void init(Properties arg0) {
        // TODO Auto-generated method stub

    }
}

2 个答案:

答案 0 :(得分:3)

同步调用CacheWriter处理程序,因此在处理程序返回之前应用程序不会继续。因此,不建议在此侦听器中执行长时间运行的操作。如果需要长时间运行的操作,请考虑通过AsyncEventListener异步处理操作。

使用ExecutorService将执行委托给不同的线程是可能的,但它是反模式的,因为它不再实现fail-fast属性,并且事件的处理不再是同步的,所以相对于应用程序完成事件,它的时间安排不会得到保证。

您可以在Geode Wiki中详细了解此主题,特别是CacheWrite and CacheListener Best Practices

希望这有帮助。

最好的问候。

答案 1 :(得分:1)

是的,它是一个很好的模式,但是删除Executor并对数据进行分区,以便GemFire的所有更新都转到一个且只有一个节点。以同样的方式对Cassandra进行分区。在Cassandra更新周围写一个写锁。仅在吞吐量较低时使用此选项。

如果您需要高吞吐量,请使用AsyncEventListener并保证用户的最终一致性。如果必须在AEL中使用Executors,请以某种方式使用它们,以便在主线程中引发异常。如果在多次尝试后更新失败,则将失败的条目写入其他区域,并在几秒或一分钟到期。当该过期时,重试该操作。继续这样做直到成功然后才会删除过期的条目。

如果更新顺序对您不重要,您将需要跟踪版本号以及您正在更新观看旧值/新值的内容。