用于Redis得分排序集的Hazelcast和Apache Ignite类似物

问题描述

我已使用RedisSorted sets构建游戏的快速排行榜解决方案。 我的任务需要执行两个主要的查询操作:

  1. 从索引A到B降序获取元素及其分数(Redis中为ZREVRANGE
  2. 按降序获取特定元素的索引和分数(在Redis中为ZREVRANK

据我所知,Redis对排序集使用特殊的数据结构,该结构将某种跳过列表与哈希表结合在一起。

现在,我想从Redis迁移到现代IMDG解决方案,并在Hazelcast和Apache Ignite之间进行选择。在Hazelcast / Apache Ignite中,Redis排序集和ZREVRANGE,ZREVRANK操作最接近的类似物是什么?

解决方法

在Hazelcast中,您可以创建IndexType.SORTED。请查看相关文档Hazelcast Reference Manual: Indexing Queries

,

似乎可以利用Apache Ignite中的query entities。 这是一个原始示例。

<bean class="org.apache.ignite.configuration.CacheConfiguration">
    <property name="name" value="testCache"/>
    <property name="queryEntities">
        <list>
            <bean class="org.apache.ignite.cache.QueryEntity">
                <property name="keyType" value="com.company.ScoreAndId"/>

                <property name="keyFields">
                    <list>
                        <value>score</value>
                        <value>id</value>
                    </list>
                </property>

                <property name="valueType" value="com.company.UserInfo"/>

                <property name="fields">
                    <map>
                        <entry key="score" value="java.lang.Long"/>
                        <entry key="id" value="java.lang.Long"/>
                        <entry key="name" value="java.lang.String"/>
                    </map>
                </property>

                <property name="indexes">
                    <list>
                        <bean class="org.apache.ignite.cache.QueryIndex">
                            <constructor-arg value="id"/>
                        </bean>
                        <bean class="org.apache.ignite.cache.QueryIndex">
                            <constructor-arg>
                                <list>
                                    <value>score</value>
                                    <value>id</value>
                                </list>
                            </constructor-arg>
                            <constructor-arg value="SORTED"/>
                        </bean>
                    </list>
                </property>
            </bean>
        </list>
    </property>
</bean>

之后,可以使用常规的SQL查询从缓存中获取数据。表名将是"USERINFO",因为它是从类型名UserInfo继承而来的,无论如何都可以reconfigure。模式来自缓存名称。 例如:

SELECT * FROM "testCache"."USERINFO" WHERE SCORE > ? AND SCORE < ?;

它将进行范围索引扫描。 您可以运行EXPLAIN命令来检查正在使用的索引(在示例中,我们有2个索引。)

explain SELECT * FROM "testCache"."USERINFO" WHERE SCORE > ? AND SCORE < ?;
,

在像IMDG这样的分布式系统中实施排行榜似乎是一项非常复杂的任务。如果我错了,请纠正我,但是ZSET在Redis中更像是本地事物,您的Sorted Set不能大于最大碎片。 我想将此问题分为两种情况:本地和分布式。

  • 本地。通常,在Ignite中,可以通过创建缓存REPLICATED来实现。可以将本地SQL查询与LIMIT/OFFSET一起使用,但据我所知,没有快速(O(log(n))索引跳转可以从具有特定编号的某行开始进一步扫描。这使得无法实现O(log(n) + m)的整体复杂性,其中m是窗口大小。从理论上讲,可以实现这一点。我已经在“ Apache Ignite开发人员”列表上启动了discussion。无论如何,这都取决于您的实际用例:您拥有多少用户,目标延迟是多少,百分位数等。
  • 已分发。在这里,它变得更加复杂,因为无法保证在使用PARTITIONED缓存的情况下,它足以从排名从ab的每个节点获取值,因为数据{{3} }(亲和力将键映射到节点)可能不是绝对偶数。这意味着您需要扫描每个节点上的整个索引,直到达到b(或上面最接近的值)为止。