如何解决Spring Data GemFire 自定义分区和性能
我们正在使用 Spring Data GemFire 服务器、客户端和定位器。我们所有的 GemFire PARTITION 区域都有复杂的键。
例如:
class Key {
String id1;
String id2;
Date date;
}
我们想根据整个密钥创建一个自定义分区。在 getobject()
方法中,我们计划返回一个 |这 3 个字段的分隔字符串。
这是最佳实践还是有其他方法可以返回对象?
我们还计划创建关键索引,在这种情况下,我们必须在 Key.id1
和 Key.id2
和 Key.date
上单独创建索引,因为我们的搜索将基于关键日期和密钥 id1、id2。
根据 GemFire 文档,我们计划使用 Functions 来提高性能。在 Filter
参数中搜索发生在特定分区
我们是否只需要发送复杂对象或我们在过滤器集中传递的 getobject
中添加的任何分区逻辑?
解决方法
首先,这个问题与您是否使用 Spring Data GemFire (SDG) 启动 GemFire(数据)服务器无关,例如使用 Gfsh .话虽如此,使用 Spring(特别是 SDG)来引导和配置您的服务器、定位器和客户端具有显着的优势。但是,我只是想在其他感兴趣的读者关注这个问题的地方做出这种区分。
通过 getObject()
方法,我假设您实际上指的是 PartitionResolver.getRoutingObject()
?见Javadoc。
一般来说,我认为在您的区域中使用简单的标量类型作为键几乎总是更可取,例如Long
、Integer
、{{ 1}} 等。大多数搜索应该基于值或值的属性(即对象)而不是键的单个组件(例如 String
)。
此外,我还要指出,我不同意 id1
Javadoc,第 1 项,它指出,“密钥类可以实现 PartitionResolver
接口启用自定义分区”。我认为出于多种原因,这是一种幼稚的方法,其中最重要的是它将您的关键类与 GemFire 结合起来。当需要 PartitionResolver
时,您应该始终选择 #2。
但是在您的情况下实际上需要 PartitionResolver
吗?
由于您的“整个”键定义了“路线”(即 PartitionResolver
类的所有属性 [ id1
,id2
,date
]),您不甚至根本不需要涉及自定义 Key
。
您只需在您的 PartitionResolver
类中正确实现 Object
equals(:Object)
和 hashCode()
方法。
提示:请记住,GemFire Regions 在基本层面上只是一个 Key
、键值 数据结构。是的,它们是分布式的(在大多数情况下)以及针对 PARTITION Regions 进行分区,但它基本上基于 java.util.Map
和密钥的“哈希”。如果您的整个密钥定义了分区(或路由),则不需要自定义 Map
。
提示:此外,PartitionResolver
Region 是一个逻辑 Region,它被划分为 113 个桶(默认情况下,暂时忽略主要和次要) 并且这些存储桶分布在集群中的(数据托管)服务器上,从而使区域在物理上分散,当然,假设您的服务器是不同机器上的独立进程。这就是构成“逻辑”区域的原因,因为对于您的应用程序来说,它只是一个完整的数据结构。无论如何。
如果键的一部分用于确定分区(或路由)或键/值对,您将实现自定义 PARTITION
。如果您想在同一物理位置(即集群中的服务器/进程和机器)将某些键/值对组合在一起,这将非常有用。
例如,假设您想根据键的 PartitionResolver
对相似的键/值对进行分组。然后……
date
现在,发生在相似日期/时间的所有条目(键/值)都将路由到逻辑分区 Region 中的同一分区(或存储桶)。当然,您可以进一步过滤要分组的日期,或者根据年/月/日或简单的年/月路由键/值对,但是您可以选择。同样,重要的是从自定义 class KeyDatePartitionResolver implements PartitionResolver {
public String getName() {
return getClass().getName();
}
public Object getRoutingObject(EntryOperation<Key,Object> entryOp) {
Key key = entryOp.getKey();
return key.getDate();
}
}
中的 Object
方法返回的 getRoutingObject(..)
实现了 PartitionResolver
和 equals(:Object)
方法。显然,Java 的 hashCode()
类 (Javadoc) 可以。
关于...
"这是创建关键索引以提高性能的正确方法吗?"
嗯,这取决于您的应用程序搜索案例。您的某些值的搜索案例是基于键的组成部分(即 [ java.util.Date
,id1
,id2
])的整体还是单独的?
例如,如果您按组合 [ date
,id1
] 以及 [ date
,id2
] 进行搜索,那么您将创建 2 (KEY) date 类中的这些字段进行 em>索引。如果您按所有 3 个字段 [ Key
,id2
] 进行搜索,那么您的 (KEY) Index 将包括所有 3 个字段。如果您按所有 3 种组合进行搜索,那么您(通常)何时需要所有 3 个 KEY 索引以获得最佳性能。
本质上,查询谓词表达式中使用的一个字段或字段组合应该被编入索引,以获得潜在的更优化性能。
但也不能保证。请记住,当值发生变化(添加、更新、删除等)时,索引 需要在某种程度上进行更新。因此,存在与索引相关的“维护成本”,您拥有的越多,潜在成本就越高。
您还必须权衡键/值对的数量与索引是否完全必要之间的利益。如果数据本质上主要是参考性的,数据集相对较小(例如 索引 时更有效。全扫描相当于 RDBMS 中的全表扫描。请记住,索引不是免费的。它们占用空间(内存)和时间(CPU)来维护。
我还要说,通常最好(再次)使用简单的键并在与键关联的值中保持“可搜索”状态。不过,这归结为设计偏好。使用(简单)键进行分区/路由。
有关其他(和相关)信息,请参阅:here、here、here 和 here。
最后,关于date
,过滤器是一组“键”(Javadoc)。这些键用于查找或路由到逻辑分区 Region 中的(桶的)分区。
如果您还使用 PARTITION Region 配置了自定义 Functions
,我相信它还会将解析器应用于传递给 {{1} } 执行 PartitionResolver
时。
但是,您只是传递整个密钥,在您的情况下是 Function
类的一个实例,您可以在其中传递多个实例(因此,“Function
”)取决于哪个要过滤的键。
无论如何,我希望这一切都有意义。
与往常一样,当提出此类问题时,根据您的 UC(或数据访问模式)、要求、数据集,情况会有很大差异。正确的做法是尝试和测试。
祝你好运!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。