Java 如何为外部存储序列化JBoss库集合?

Java 如何为外部存储序列化JBoss库集合?,java,concurrency,redis,drools,Java,Concurrency,Redis,Drools,这实际上可能与Drools本身无关,但可能只是一个Java本机解决方案。我只是一个彻头彻尾的JavaNoob,继承了一个项目,所以我试图了解最佳实践 我们有一个基于规则的多租户系统,其中业务规则可以由我们的客户动态配置。我们将每个客户机的编译规则存储在一个ConcurrentHashMap中,如下所示 ConcurrentMap规则=新建ConcurrentHashMap(); 其中,字符串是表示每个唯一客户端的UUID。然而,这样做的问题是横向扩展计算是一个问题,因为这只是一个在每次更改时

这实际上可能与Drools本身无关,但可能只是一个Java本机解决方案。我只是一个彻头彻尾的JavaNoob,继承了一个项目,所以我试图了解最佳实践

我们有一个基于规则的多租户系统,其中业务规则可以由我们的客户动态配置。我们将每个客户机的编译规则存储在一个
ConcurrentHashMap
中,如下所示


ConcurrentMap规则=新建ConcurrentHashMap();

其中,
字符串
是表示每个唯一客户端的UUID。然而,这样做的问题是横向扩展计算是一个问题,因为这只是一个在每次更改时重新编译的内存哈希映射。如果我们扩展它,每个客户机都需要倾听新规则的更改并在每次更改时重新编译,这感觉像是浪费,因为它们总是会产生相同的结果

我的最终目标是将这些计算出的规则存储在JVM之外,以便多个实例可以共享已编译的规则,并且这些实例中的任何一个都可以安全、并发地重新编译特定客户机的规则,而可能需要该客户机规则的所有其他实例将等待

因此,我的想法是将Redis用作k/v锁/存储,其中密钥是客户机id,值是Drools KieBase对象的序列化版本。重新计算将使用(或某些类似的锁定算法)锁定该密钥上的redis存储,以便需要该客户端id的KieBase的其他实例将等待编译完成并写回db

所以我有几个问题:

  • 这个KieBase对象的序列化是Drools特有的还是Java中有针对任何对象的通用编组序列化机制(这是推荐的吗?)
  • 你想做些我想要的事情吗?如果是这样的话,有没有人能给我指出正确的方向?我基本上需要为每个客户机锁定一个密钥,以便在计算一个实例时多个实例将被阻塞,但我最好不要锁定整个数据库,只锁定hashmap中的一个条目

  • 简单的ObjectOutputStream足以序列化KieBase对象。在下面,它用于写入文件,但您可以通过写入ByteArrayOutputStream并以任意形式获取结果来创建字符串或字节[]

    KieBase kieBase = kieContainer.getKieBase();
    FileOutputStream fos = new FileOutputStream( OUTPATH );
    ObjectOutputStream oos = new ObjectOutputStream( fos );
    oos.writeObject( kieBase );
    oos.close();
    
    FileInputStream fis = new FileInputStream( OUTPATH );
    ObjectInputStream ois = new ObjectInputStream( fis );
    KieBase kieBase1 = (KieBase)ois.readObject();
    ois.close();
    
    至于锁定,这取决于是否需要针对多个并行运行的应用程序(在网络中)锁定外部表示,或者是否有一个(服务器)应用程序保留HashMap中的所有内容。在后一种情况下,任何Java对象都有一个监视器:

    synchronized( idString ) {
        idString.wait();    // or overloaded form with timeout
    }
    
    // different thread 
    synchronized( idString ){
        idString.notify();
    }
    
    您可以参考Brian Goetz的书《Java并发性的实践》

    编辑
    任何像样的数据库都有写锁定机制。此外,在您的情况下,您甚至可以使用MS Windows和所有Unice上提供的简单文件存储和文件锁定进行管理。

    简单的ObjectOutputStream足以序列化KieBase对象。在下面,它用于写入文件,但您可以通过写入ByteArrayOutputStream并以任意形式获取结果来创建字符串或字节[]

    KieBase kieBase = kieContainer.getKieBase();
    FileOutputStream fos = new FileOutputStream( OUTPATH );
    ObjectOutputStream oos = new ObjectOutputStream( fos );
    oos.writeObject( kieBase );
    oos.close();
    
    FileInputStream fis = new FileInputStream( OUTPATH );
    ObjectInputStream ois = new ObjectInputStream( fis );
    KieBase kieBase1 = (KieBase)ois.readObject();
    ois.close();
    
    至于锁定,这取决于是否需要针对多个并行运行的应用程序(在网络中)锁定外部表示,或者是否有一个(服务器)应用程序保留HashMap中的所有内容。在后一种情况下,任何Java对象都有一个监视器:

    synchronized( idString ) {
        idString.wait();    // or overloaded form with timeout
    }
    
    // different thread 
    synchronized( idString ){
        idString.notify();
    }
    
    您可以参考Brian Goetz的书《Java并发性的实践》

    编辑
    任何像样的数据库都有写锁定机制。此外,在您的情况下,您甚至可以使用MS Windows和所有Unice上提供的简单文件存储和文件锁定进行管理。

    谢谢。我刚刚阐明了我在上面的最终目标,即在“依赖”场景中实现前者,即在多个正在运行的java进程之间共享此hashmap。虽然这给了我一个好的开始,但我会调查一下ByteArray的事情。看来我可以用绝地武士直接在Redis中储存ByteArray。至于锁定,我不确定我是否可以不使用Redis事务,或者我是否需要更高级的算法,比如Redisson doesAny Delege DB都有写锁定机制。此外,在您的情况下,您甚至可以使用MS Windows和所有Unice上提供的简单文件存储和文件锁定进行管理。我需要db的公共接口,以便可以水平扩展。我想最终我发现Redisson可能会做我想做的事。它将处理分布式并发问题,并允许我将对象序列化为可重用的对象。我刚刚阐明了我在上面的最终目标,即在“依赖”场景中实现前者,即在多个正在运行的java进程之间共享此hashmap。虽然这给了我一个好的开始,但我会调查一下ByteArray的事情。看来我可以用绝地武士直接在Redis中储存ByteArray。至于锁定,我不确定我是否可以不使用Redis事务,或者我是否需要更高级的算法,比如Redisson doesAny Delege DB都有写锁定机制。此外,在您的情况下,您甚至可以使用MS Windows和所有Unice上提供的简单文件存储和文件锁定进行管理。我需要db的公共接口,以便可以水平扩展。我想最终我发现Redisson可能会做我想做的事。它将处理分布式并发问题,并允许我将对象序列化到redis中