Search code examples
postgresqlcachingignite

Apache Ignite automatically load cache from 3rd party database (postgresql with sql schema)


I am currently building an application with different ignite configurations. Right now, I am exploring the cache features of Ignite. My goal is to use the Ignite only as a cache. The data should be stored in a 3rd party database (postgres). I use the tpc-h data schema in my database. So, it's not a key-value-store, but ordinary sql.

Current situation: I have a postgres database (database-name: "db") with a "Nation" table. The table is filled with a few entries (Postgres Table "Nation"). I also have already built up an Ignite-Cluster in my Google-Kubernetes-Engine. I use my own Ignite-Container-Image. It's basically the official one with the postgresql-driver added to the classpath. My ignite-configuration looks like this:

<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">

    <!-- Data source bean -->
    <bean id="postgresDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://postgres-service:5432/db" />
        <property name="username" value="#################" />
        <property name="password" value="#################" />
    </bean>
    <!-- Ignite Configuration -->
    <bean class="org.apache.ignite.configuration.IgniteConfiguration">
        <property name="cacheConfiguration">
            <list>
                <!-- Configuration for NationCache -->
                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <property name="name" value="NationCache"/>
                    <property name="cacheMode" value="PARTITIONED"/>
                    <property name="atomicityMode" value="ATOMIC"/>
                    <property name="cacheStoreFactory">
                        <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
                            <property name="dataSourceBean" value="postgresDataSource"/>
                            <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="NationCache"/>
                                        <property name="keyType" value="java.lang.Integer"/>
                                        <property name="valueType" value="PathToClass.Nation"/>
                                        <!--Specify the schema if applicable -->
                                        <property name="databaseSchema" value="public"/>
                                        <property name="databaseTable" value="nation"/>
                                        <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="n_nationkey"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="n_nationkey"/>
                                                </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="n_nationkey"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="n_nationkey"/>
                                                </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="n_name"/>
                                                    <constructor-arg value="java.lang.String"/>
                                                    <constructor-arg value="n_name"/>
                                                </bean>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.INTEGER"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="n_regionkey"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="n_regionkey"/>
                                                </bean>
                                            </list>
                                        </property>
                                    </bean>
                                </list>
                            </property>
                        </bean>
                    </property>
                    <property name="readThrough" value="true"/>
                    <property name="writeThrough" value="true"/>
                    <!-- Configure query entities if you want to use SQL queries -->
                    <property name="queryEntities">
                        <list>
                            <bean class="org.apache.ignite.cache.QueryEntity">
                                <property name="keyType" value="java.lang.Integer"/>
                                <property name="valueType" value="PathToClass.Nation"/>
                                <property name="keyFieldName" value="n_nationkey"/>
                                <property name="keyFields">
                                    <list>
                                        <value>n_nationkey</value>
                                    </list>
                                </property>
                                <property name="fields">
                                    <map>
                                    <entry key="n_nationkey" value="java.lang.Integer"/>
                                        <entry key="n_name" value="java.lang.String"/>
                                        <entry key="n_regionkey" value="java.lang.Integer"/>
                                    </map>
                                </property>
                            </bean>
                        </list>
                    </property>
                </bean>
                <!-- Provide similar configurations for other caches/tables -->
            </list>
        </property>
    </bean>
</beans>

Questions: How can I automatically load my cache with the data from the postgresql database? Is there a way to load the cache via cmd in the container?

Further explanation: As far as I have understood the caching feature of Ignite, I HAVE TO load the sql data to the cache to be able to work with it (doing selects, etc.). I haven't found a way to load the data to cache without writing a separate java project, that loads the cache via IgniteCache#loadCache(). That worked fine, but I had to start it manually... There must be a way to load the cache more easily than writing a separate java project just for loading the cache. Besides this project I didn't have to work with java and could work with the container alone.


Solution

  • Unfortunately, there is no built-in mechanism to trigger the #loadCache method from outside of the cluster therefore it's required to write some auxiliary code. But, once it's written you might just wrap it into s compute task and invoke it using, say, REST API.