[英]Spring Data GemFire custom partition and performance
我們正在使用 Spring Data GemFire 服務器、客戶端和定位器。 我們所有的 GemFire PARTITION Regions 都有復雜的鍵。
例如:
class Key {
String id1;
String id2;
Date date;
}
我們想根據整個密鑰創建一個自定義分區。 在getObject()
方法中,我們計划返回一個 | 這 3 個字段的分隔字符串。
這是最佳做法還是有其他方法可以返回 object?
我們還計划創建關鍵索引,在這種情況下,我們必須分別在Key.id1
和Key.id2
和Key.date
上創建索引,因為我們的搜索將基於關鍵日期和關鍵 id1、id2。
這是創建關鍵索引以提高性能的正確方法嗎?
根據 GemFire 文檔,我們計划使用 Functions 來提高性能。 在Filter
參數中搜索發生在特定分區
我們是否只需要發送復雜的 object 或我們在getObject
中添加的任何分區邏輯並傳入過濾器集?
首先,這個問題與您是否使用Spring Data GemFire (SDG) 啟動 GemFire(數據)服務器無關,例如使用Gfsh 。 話雖如此,使用Spring (特別是 SDG)來引導和配置您的服務器、定位器和客戶端具有顯着優勢。 但是,我只是想在這個問題與其他感興趣的讀者有關的地方進行區分。
通過getObject()
方法,我假設您實際上指的是PartitionResolver.getRoutingObject()
? 請參閱Javadoc 。
一般來說,我想說在您的Regions中使用簡單的標量類型作為鍵幾乎總是更可取的,例如Long
、 Integer
、 String
等。大多數搜索應該基於值或值的屬性(即對象)而不是密鑰的單個組件(例如id1
)。
此外,我還要指出,我不同意PartitionResolver
Javadoc項目符號 #1,其中指出“密鑰 class 可以實現PartitionResolver
接口以啟用自定義分區”。 我認為這是一種天真的方法,原因有很多,其中最重要的是它將您的密鑰 class 與 GemFire 耦合。 當需要PartitionResolver
時,您應該始終首選 #2。
但是在您的情況下真的需要PartitionResolver
嗎?
由於您的“整個”鍵定義了“路線”(即Key
類的所有屬性 [ id1
、 id2
、 date
]),因此您甚至根本不需要涉及自定義PartitionResolver
。
您只需在您的Key
class 中正確實現Object
equals(:Object)
和hashCode()
方法。
提示:請記住,基本級別的 GemFire區域只是一個
java.util.Map
鍵值數據結構。 是的,它們是分布式的(在大多數情況下)以及為 PARTITION Regions分區,但它基本上基於Map
和您的密鑰的“哈希”。 如果您的整個鍵定義了分區(或路由),則不需要自定義PartitionResolver
。
提示:此外,
PARTITION
區域是一個邏輯區域,它分為 113 個存儲桶(默認情況下,暫時忽略主存儲區和次存儲區),這些存儲桶分布在集群中的(數據托管)服務器上,從而使該區域當然,假設您的服務器是不同機器上的單獨進程,則物理分散。 這就是構成“邏輯”區域的原因,因為對於您的應用程序來說,它只是 1 個整體數據結構。 反正。
如果鍵的一部分用於確定分區(或路由)或鍵/值對,您將實現自定義PartitionResolver
。 如果您想在同一物理位置(即集群中的服務器/進程和機器)將某些鍵/值對組合在一起,這很有用。
例如,假設您想根據鍵的date
對相似的鍵/值對進行分組。 然后...
class KeyDatePartitionResolver implements PartitionResolver {
public String getName() {
return getClass().getName();
}
public Object getRoutingObject(EntryOperation<Key, Object> entryOp) {
Key key = entryOp.getKey();
return key.getDate();
}
}
現在,發生在相似日期/時間的所有條目(鍵/值)都將被路由到邏輯 PARTITION Region中的同一分區(或存儲桶)。 當然,您可以進一步過濾要分組的日期,或根據年/月/日或簡單的年/月路由鍵/值對,但您可以選擇。 同樣,重要的是從自定義PartitionResolver
中的Object
getRoutingObject(..)
方法返回的 Object 實現了equals(:Object)
和hashCode()
方法。 顯然,Java 的java.util.Date
class ( Javadoc ) 可以。
關於...
“這是為提高性能而創建關鍵索引的正確方法嗎? ”
好吧,這取決於您的應用程序搜索案例。 您對某些值的搜索案例是集體還是單獨基於密鑰的組件(即 [ id1
、 id2
、 date
])?
例如,如果您通過組合 [ id1
, date
] 以及 [ id2
, date
] 進行搜索,那么您將使用來自Key
class 的這些字段創建 2 個(KEY)索引。 如果您按所有 3 個字段 [ id1
、 id2
、 date
] 進行搜索,那么您的 (KEY)索引將包括所有 3 個字段。 如果您通過所有 3 個組合進行搜索,那么(通常)需要所有 3 個 KEY索引以獲得最佳性能。
本質上,查詢謂詞表達式中使用的字段或字段組合應該被索引以獲得可能更優化的性能。
但也不能保證。 請記住,當值更改(添加、更新、刪除等)時,索引需要在某種程度上更新。 因此,存在與索引相關的“維護成本”,您擁有的越多,它的潛在成本就越高。
您還必須權衡鍵/值對的數量和索引是否有必要之間的好處。 如果數據本質上主要是參考數據,數據集相對較小(例如,可能 < 1000 個條目),那么有時完全掃描在性能上仍然比使用Index時更有效。 全掃描相當於 RDBMS 中的全表掃描。 請記住,索引不是免費的。 它們占用空間(內存)和時間(CPU)來維護。
我還要說,通常最好(再次)使用簡單的鍵並在與鍵關聯的值中保持“可搜索”state。 不過,這歸結為設計偏好。 使用(簡單)鍵進行分區/路由。
有關其他(和相關)信息,請參閱: 此處、 此處、 此處和此處。
最后,關於Functions
,過濾器是一組“鍵”( Javadoc )。 這些鍵用於查找或路由到邏輯 PARTITION Region中的(存儲桶)分區。
如果您還使用 PARTITION Region配置了自定義PartitionResolver
,我相信它也會將解析器應用於在執行Function
時傳遞給Function
的過濾(或一組鍵)。
但是,您只是傳遞整個密鑰,在您的情況下,它是Key
class 的一個實例,您可以在其中傳遞多個實例(因此,“ Set
”),具體取決於您要過濾的密鑰。
無論如何,我希望這一切都有意義。
與往常一樣,當這類問題或被問到時,它會根據您的 UC(或數據訪問模式)、要求、數據集而顯着變化。 在這里做的正確的事情是嘗試和測試。
祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.