Apache Ignite Join Query возвращает неверные результаты из-за несовместимости данных - PullRequest
0 голосов
/ 19 мая 2019

Я новичок в Ignite и слежу за различными блогами, чтобы понять необходимую конфигурацию.

Для начала я использовал данные "кинообъектива" (Movies & Ratings) и использовал Ignite Web Console для генерациитребуемая конфигурация.

Ниже приведены необходимые сведения о моем коде:

1) Структура таблицы MySQL

CREATE TABLE movie (movie_idINTEGER, название фильма VARCHAR (250), жанр VARCHAR (250), CONSTRAINT pk_movie ПЕРВИЧНЫЙ КЛЮЧ (movie_id);user_id, movie_id));

2) Ignite Config File в Spring Boot Project (автоматически генерируется Ignite Web Console)

<?xml version="1.0" encoding="UTF-8"?>

<!-- This file was generated by Ignite Web Console (05/15/2019, 18:37) -->

<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.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util.xsd">
    <!-- Load external properties file. -->
    <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:secret.properties"/>
    </bean>

    <!-- Data source beans will be initialized from external properties file. -->
    <bean id="dsGeneric_Movielens" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${dsGeneric_Movielens.jdbc.url}"/>
        <property name="user" value="${dsGeneric_Movielens.jdbc.username}"/>
        <property name="password" value="${dsGeneric_Movielens.jdbc.password}"/>
    </bean>

    <bean class="org.apache.ignite.configuration.IgniteConfiguration">
        <property name="igniteInstanceName" value="ImportedCluster"/>

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

        <property name="cacheConfiguration">
            <list>
                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <property name="name" value="MoviesCache"/>
                    <property name="cacheMode" value="REPLICATED"/>
                    <property name="atomicityMode" value="ATOMIC"/>

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

                            <property name="types">
                                <list>
                                    <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
                                        <property name="cacheName" value="MoviesCache"/>
                                        <property name="keyType" value="java.lang.Integer"/>
                                        <property name="valueType" value="com.learnwithmanoj.ignite.model.Movies"/>
                                        <property name="databaseSchema" value="movielens"/>
                                        <property name="databaseTable" value="movies"/>

                                        <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="movie_id"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="movieId"/>
                                                </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="movie_name"/>
                                                    <constructor-arg value="java.lang.String"/>
                                                    <constructor-arg value="movieName"/>
                                                </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="genre"/>
                                                    <constructor-arg value="java.lang.String"/>
                                                    <constructor-arg value="genre"/>
                                                </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="com.learnwithmanoj.ignite.model.Movies"/>
                                <property name="keyFieldName" value="movieId"/>

                                <property name="keyFields">
                                    <list>
                                        <value>movieId</value>
                                    </list>
                                </property>

                                <property name="fields">
                                    <map>
                                        <entry key="movieName" value="java.lang.String"/>
                                        <entry key="genre" value="java.lang.String"/>
                                        <entry key="movieId" value="java.lang.Integer"/>
                                    </map>
                                </property>

                                <property name="aliases">
                                    <map>
                                        <entry key="movieId" value="movie_id"/>
                                        <entry key="movieName" value="movie_name"/>
                                    </map>
                                </property>
                            </bean>
                        </list>
                    </property>
                </bean>

                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <property name="name" value="RatingsCache"/>
                    <property name="cacheMode" value="REPLICATED"/>
                    <property name="atomicityMode" value="ATOMIC"/>

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

                            <property name="types">
                                <list>
                                    <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
                                        <property name="cacheName" value="RatingsCache"/>
                                        <property name="keyType" value="com.learnwithmanoj.ignite.model.RatingsKey"/>
                                        <property name="valueType" value="com.learnwithmanoj.ignite.model.Ratings"/>
                                        <property name="databaseSchema" value="movielens"/>
                                        <property name="databaseTable" value="ratings"/>

                                        <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="user_id"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="userId"/>
                                                </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="movie_id"/>
                                                    <constructor-arg value="int"/>
                                                    <constructor-arg value="movieId"/>
                                                </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.REAL"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="rating"/>
                                                    <constructor-arg value="java.lang.Double"/>
                                                    <constructor-arg value="rating"/>
                                                </bean>

                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.TIMESTAMP"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="timestamp"/>
                                                    <constructor-arg value="java.sql.Timestamp"/>
                                                    <constructor-arg value="timestamp"/>
                                                </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="com.learnwithmanoj.ignite.model.RatingsKey"/>
                                <property name="valueType" value="com.learnwithmanoj.ignite.model.Ratings"/>

                                <property name="keyFields">
                                    <list>
                                        <value>userId</value>
                                        <value>movieId</value>
                                    </list>
                                </property>

                                <property name="fields">
                                    <map>
                                        <entry key="userId" value="java.lang.Integer"/>
                                        <entry key="movieId" value="java.lang.Integer"/>
                                        <entry key="rating" value="java.lang.Double"/>
                                        <entry key="timestamp" value="java.sql.Timestamp"/>
                                    </map>
                                </property>

                                <property name="aliases">
                                    <map>
                                        <entry key="userId" value="user_id"/>
                                        <entry key="movieId" value="movie_id"/>
                                    </map>
                                </property>

                                <property name="indexes">
                                    <list>
                                        <bean class="org.apache.ignite.cache.QueryIndex">
                                            <property name="name" value="fk_movie_id"/>
                                            <property name="indexType" value="SORTED"/>

                                            <property name="fields">
                                                <map>
                                                    <entry key="movieId" value="false"/>
                                                </map>
                                            </property>
                                        </bean>
                                    </list>
                                </property>
                            </bean>
                        </list>
                    </property>
                </bean>
            </list>
        </property>
    </bean>
</beans>

3) Ignite Config File в папке установки Ignite

<?xml version="1.0" encoding="UTF-8"?>

<!-- This file was generated by Ignite Web Console (05/15/2019, 08:52) -->

<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.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util.xsd">
    <!-- Load external properties file. -->
    <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:secret.properties"/>
    </bean>

    <!-- Data source beans will be initialized from external properties file. -->
    <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${datasource.jdbc.url}"/>
        <property name="user" value="${datasource.jdbc.username}"/>
        <property name="password" value="${datasource.jdbc.password}"/>
    </bean>

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

        <property name="igniteInstanceName" value="MovieRatingsCluster"/>

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

    </bean>
</beans>

Положение проблемы:

Когда я запускаю приложение Spring Boot в качестве автономного узла Igniteтогда вседанные из базы данных MySQL синхронизируются в узел Ignite, как и ожидалось.Кроме того, если я пытаюсь соединить таблицу рейтингов и фильмов, она соединяется правильно и дает правильный результат.

Используемый запрос на присоединение:

выберите r.movie_id, m.movie_name, count (r.rating) как количество из «RatingsCache» .ratings r внутреннее объединение «MoviesCache» .movies m, где r.movie_id = m.movie_id, группа по r.movie_id, порядок по счету, ограничение 5;

Теперь приступим к проблеме.Если я выполняю одно и то же тестирование с использованием более одного узла, то соединение начинает давать неверные результаты из-за отсутствия данных.

Может кто-нибудь подсказать мне правильный набор конфигурации, который необходимо добавить висправить проблему соединения в режиме разбиения?

Я даже пытался добавить приведенную ниже конфигурацию.

<property name="cacheKeyConfiguration">
    <list>
        <bean class="org.apache.ignite.cache.CacheKeyConfiguration">
            <property name="typeName" value="com.learnwithmanoj.ignite.model.RatingsKey" />
            <property name="affinityKeyFieldName" value="movie_id" />
        </bean>
    </list>
</property>

Но получил ошибку ниже.

Вызвано: org.apache.ignite.binary.BinaryObjectException: бинарный тип имеет разные поля ключей сродства

1 Ответ

1 голос
/ 20 мая 2019

Ваше решение должно работать. Сначала необходимо очистить каталог marshaller/ в папке Ignite home dir на всех узлах, а затем перезапустить эти узлы.

Также может потребоваться указать имя ключевого поля заглавными буквами: MOVIE_ID.

...