首页 > 解决方案 > 在 Ignite 服务器节点中动态创建缓存并将其链接到 PostgreSql 表

问题描述

我有一个 Ignite 服务器节点一个厚 Java 客户端。我可以通过调用客户端节点在服务器节点中创建新的缓存(我已经公开了 REST API)。

我有一个PostgreSQL 数据库,其中实现了模式分离的多租户,这意味着: 在此处输入图像描述

这里 Schema1 和 Schema2 中的 Table1 在属性上是相同的。由于它属于不同的模式,它将为不同的租户保存值。. 在 PostgreSQL中,当新租户是项目的一部分时,可以动态创建新的模式和表。.

我能够创建一个配置,将所有现有模式中的 Table1 加载到 Ignite Server 节点,并将值从 DB 加载到表中。通过客户,我也能够获得价值。

问题: 我无法从客户端节点创建缓存(用于新模式中新创建的表)并将其链接到 PostgreSQL。

在 Ignite 开发人员文档中,我无法直接解决我的问题。谁能帮我解决这个问题的正确方法,并链接到一个创建动态缓存并将其链接到数据库的示例。

我收到以下异常,我知道我没有附加代码,如果您需要代码来更好地理解问题,那么我会将代码推送到 github 并在问题中链接。

动态缓存创建:https : //www.gridgain.com/docs/latest/developers-guide/key-value-api/basic-cache-operations 这里使用 ccfg.setCacheStoreFactory(cacheStoreFactory) 我已经链接了数据库。

注意:如果我在服务器模式“cfg.setClientMode(false)”下运行客户端,那么我能够成功创建一个新的缓存并链接到数据库。这是否意味着只能在服务器中创建新的缓存。?

    2021-07-23 00:03:39.574 ERROR 8036 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is javax.cache.CacheException: class org.apache.ignite.IgniteCheckedException: Failed to complete exchange process.] with root cause

org.apache.ignite.IgniteCheckedException: Failed to complete exchange process.
    at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.createExchangeException(GridDhtPartitionsExchangeFuture.java:3372) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.sendExchangeFailureMessage(GridDhtPartitionsExchangeFuture.java:3400) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.finishExchangeOnCoordinator(GridDhtPartitionsExchangeFuture.java:3496) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.onAllReceived(GridDhtPartitionsExchangeFuture.java:3477) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.distributedExchange(GridDhtPartitionsExchangeFuture.java:1608) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.init(GridDhtPartitionsExchangeFuture.java:929) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager$ExchangeWorker.body0(GridCachePartitionExchangeManager.java:3251) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager$ExchangeWorker.body(GridCachePartitionExchangeManager.java:3097) ~[ignite-core-8.7.9.jar:8.7.9]
    at org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:119) ~[ignite-core-8.7.9.jar:8.7.9]
    at java.lang.Thread.run(Thread.java:748) ~[na:na]
    Suppressed: org.apache.ignite.IgniteCheckedException: Failed to initialize exchange locally [locNodeId=2753929a-755e-4243-b8d0-693e42b1a078]
        at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.onCacheChangeRequest(GridDhtPartitionsExchangeFuture.java:1345) ~[ignite-core-8.7.9.jar:8.7.9]
        at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.init(GridDhtPartitionsExchangeFuture.java:855) ~[ignite-core-8.7.9.jar:8.7.9]
        ... 4 common frames omitted
    Caused by: org.apache.ignite.IgniteException: Failed to enrich cache configuration [cacheName=Users_cuddle_nand]
        at org.apache.ignite.internal.processors.cache.CacheConfigurationEnricher.enrich(CacheConfigurationEnricher.java:128)
        at org.apache.ignite.internal.processors.cache.CacheConfigurationEnricher.enrich(CacheConfigurationEnricher.java:61)
        at org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareCacheContext(GridCacheProcessor.java:1881)
        at org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareCacheStart(GridCacheProcessor.java:1849)
        at org.apache.ignite.internal.processors.cache.GridCacheProcessor.lambda$prepareStartCaches$55a0e703$1(GridCacheProcessor.java:1724)
        at org.apache.ignite.internal.processors.cache.GridCacheProcessor.lambda$prepareStartCachesIfPossible$14(GridCacheProcessor.java:1694)
        at org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareStartCaches(GridCacheProcessor.java:1721)
        at org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareStartCachesIfPossible(GridCacheProcessor.java:1692)
        at org.apache.ignite.internal.processors.cache.CacheAffinitySharedManager.processCacheStartRequests(CacheAffinitySharedManager.java:971)
        at org.apache.ignite.internal.processors.cache.CacheAffinitySharedManager.onCacheChangeRequest(CacheAffinitySharedManager.java:857)
        at org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture.onCacheChangeRequest(GridDhtPartitionsExchangeFuture.java:1334)
        ... 5 common frames omitted
    Caused by: org.apache.ignite.IgniteException: Failed to deserialize field storeFactory
        at org.apache.ignite.internal.processors.cache.CacheConfigurationEnricher.deserialize(CacheConfigurationEnricher.java:153)
        at org.apache.ignite.internal.processors.cache.CacheConfigurationEnricher.enrich(CacheConfigurationEnricher.java:121)
        ... 15 common frames omitted
    Caused by: org.apache.ignite.IgniteCheckedException: Failed to deserialize object with given class loader: sun.misc.Launcher$AppClassLoader@18b4aac2
        at org.apache.ignite.marshaller.jdk.JdkMarshaller.unmarshal0(JdkMarshaller.java:148)
        at org.apache.ignite.marshaller.AbstractNodeNameAwareMarshaller.unmarshal(AbstractNodeNameAwareMarshaller.java:92)
        at org.apache.ignite.marshaller.jdk.JdkMarshaller.unmarshal0(JdkMarshaller.java:162)
        at org.apache.ignite.marshaller.AbstractNodeNameAwareMarshaller.unmarshal(AbstractNodeNameAwareMarshaller.java:80)
        at org.apache.ignite.internal.util.IgniteUtils.unmarshal(IgniteUtils.java:10478)
        at org.apache.ignite.internal.processors.cache.CacheConfigurationEnricher.deserialize(CacheConfigurationEnricher.java:150)
        ... 16 common frames omitted
    Caused by: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory.dataSrcFactory of type javax.cache.configuration.Factory in instance of org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory
        at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2301)
        at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1431)
        at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2411)
        at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2329)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2187)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1667)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:503)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:461)
        at org.apache.ignite.marshaller.jdk.JdkMarshaller.unmarshal0(JdkMarshaller.java:140)
        ... 21 common frames omitted

标签: cachingignitegridgain

解决方案


我的猜测是,您无法通过 Ignite 在 Postgres 中轻松创建新缓存,因为所有缓存都必须在配置中提供,并且它们也必须与 Postgres 中的基表匹配。

前段时间我将 Ignite 与 Postgres 集成,并且能够使用以下配置:

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
     http://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util-3.1.xsd">

    <bean id="postgre_con" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
        <property name="username" value="postgres" />
        <property name="password" value="qwerty" />
        <property name="connectionProperties">
            <props>
                <prop key="socketTimeout">10</prop>
            </props>
        </property>
    </bean>

    <bean id="grid.cfg"
          class="org.apache.ignite.configuration.IgniteConfiguration">

        <property name="failureDetectionTimeout" value="60000"/>
        <property name="clientFailureDetectionTimeout" value="60000"/>
        <property name="cacheConfiguration">
            <list>
                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <property name="name" value="Person"/>
                    <property name="cacheMode" value="PARTITIONED"/>
                    <property name="atomicityMode" value="TRANSACTIONAL"/>
                    <property name="sqlSchema" value="PUBLIC"/>

                    <property name="keyConfiguration">
                        <list>
                            <bean class="org.apache.ignite.cache.CacheKeyConfiguration">
                                <constructor-arg name="keyCls" value="org.gridgain.essilor.model.Person"/>
                            </bean>
                        </list>
                    </property>

                    <property name="cacheStoreFactory">
                        <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
                            <property name="dataSourceBean" value="postgre_con"/>
                            <property name="dialect">
                                <bean class="org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect"/>
                            </property>

                            <property name="types">
                                <list>
                                    <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
                                        <property name="cacheName" value="Person"/>
                                        <property name="keyType" value="java.lang.Integer"/>
                                        <property name="valueType" value="org.gridgain.essilor.model.Person"/>
                                        <property name="databaseSchema" value="PUBLIC"/>
                                        <property name="databaseTable" value="Person"/>

                                        <property name="keyFields">
                                            <list>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.INTEGER"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="person_id"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="person_id"/>
                                                </bean>
                                            </list>
                                        </property>

                                        <property name="valueFields">
                                            <list>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.INTEGER"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="company_id"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="company_id"/>
                                                </bean>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.VARCHAR"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="person_name"/>
                                                    <constructor-arg value="java.lang.String"/>
                                                    <constructor-arg value="person_name"/>
                                                </bean>
                                            </list>
                                        </property>
                                    </bean>
                                </list>
                            </property>
                        </bean>
                    </property>

                    <property name="readThrough" value="true"/>
                    <property name="writeThrough" value="true"/>

                    <!-- Configure type metadata to enable queries. -->
                    <property name="queryEntities">
                        <list>
                            <bean class="org.apache.ignite.cache.QueryEntity">
                                <property name="keyType" value="java.lang.Integer"/>
                                <property name="valueType" value="org.gridgain.essilor.model.Person"/>
                                <property name="tableName" value="Person"/>
                                <property name="keyFieldName" value="person_id"/>

                                <property name="fields">
                                    <map>
                                        <entry key="person_id" value="java.lang.Integer"/>
                                        <entry key="company_id" value="java.lang.Integer"/>
                                        <entry key="person_name" value="java.lang.String"/>
                                    </map>
                                </property>
                            </bean>
                        </list>
                    </property>
                </bean>
                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <property name="name" value="Company"/>
                    <property name="cacheMode" value="PARTITIONED"/>
                    <property name="atomicityMode" value="TRANSACTIONAL"/>
                    <property name="sqlSchema" value="PUBLIC"/>

                    <property name="keyConfiguration">
                        <list>
                            <bean class="org.apache.ignite.cache.CacheKeyConfiguration">
                                <constructor-arg name="keyCls" value="org.gridgain.essilor.model.Company"/>
                            </bean>
                        </list>
                    </property>

                    <property name="cacheStoreFactory">
                        <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
                            <property name="dataSourceBean" value="postgre_con"/>
                            <property name="dialect">
                                <bean class="org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect"/>
                            </property>

                            <property name="types">
                                <list>
                                    <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
                                        <property name="cacheName" value="Company"/>
                                        <property name="keyType" value="java.lang.Integer"/>
                                        <property name="valueType" value="org.gridgain.essilor.model.Company"/>
                                        <property name="databaseSchema" value="PUBLIC"/>
                                        <property name="databaseTable" value="Company"/>

                                        <property name="keyFields">
                                            <list>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.INTEGER"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="company_id"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="company_id"/>
                                                </bean>
                                            </list>
                                        </property>

                                        <property name="valueFields">
                                            <list>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.VARCHAR"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="company_name"/>
                                                    <constructor-arg value="java.lang.String"/>
                                                    <constructor-arg value="company_name"/>
                                                </bean>
                                            </list>
                                        </property>
                                    </bean>
                                </list>
                            </property>
                        </bean>
                    </property>

                    <property name="readThrough" value="true"/>
                    <property name="writeThrough" value="true"/>

                    <property name="queryEntities">
                        <list>
                            <bean class="org.apache.ignite.cache.QueryEntity">
                                <property name="keyType" value="java.lang.Integer"/>
                                <property name="valueType" value="org.gridgain.essilor.model.Company"/>
                                <property name="tableName" value="Company"/>
                                <property name="keyFieldName" value="company_id"/>

                                <property name="fields">
                                    <map>
                                        <entry key="company_id" value="java.lang.Integer"/>
                                        <entry key="company_name" value="java.lang.String"/>
                                    </map>
                                </property>
                            </bean>
                        </list>
                    </property>
                </bean>
            </list>
        </property>

        <property name="dataStorageConfiguration">
            <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
                <property name="defaultDataRegionConfiguration">
                    <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
                        <property name="persistenceEnabled" value="true"/>
                        <property name="name" value="Default_Region"/>
                        <property name="initialSize" value="#{500L * 1024 * 1024}"/>
                        <property name="maxSize" value="#{1L * 1024 * 1024 * 1024}"/>
                    </bean>
                </property>


                <property name="walMode" value="LOG_ONLY"/>
                <property name="writeThrottlingEnabled" value="true"/>
                <property name="pageSize" value="4096"/>
            </bean>
        </property>

        <property name="discoverySpi">
            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                <property name="ipFinder">
                    <bean
                        class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
                        <property name="addresses">
                            <list>
                                <value>127.0.0.1:47500..47501</value>
                            </list>
                        </property>
                    </bean>
                </property>
            </bean>
        </property>

        <property name="communicationSpi">
            <bean
                class="org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi">
                <property name="localPort" value="48100"/>
                <property name="localPortRange" value="10"/>
                <property name="socketWriteTimeout" value="300000"/>
            </bean>
        </property>
    </bean>
</beans>

我的猜测是,当您尝试更改客户端中的配置时,在服务器端它无法与其配置合并。这里似乎可行的唯一方法是将新配置应用于整个集群,丢弃所有缓存的数据(升级后您应该从 Postgres 再次加载它)。


推荐阅读