간혹 특정 shard 로 색인 문서가 몰리는 경우가 있습니다.
이럴경우 _id 값에 대한 key 조합을 확인해야 할 필요가 있는데요.
es 내부에서 사용하는 hash 함수를 이용해서 간단하게 테스트 해볼수 있습니다.
[테스트 코드]
public class EsHashPartitionTest {
private static final Logger log = LoggerFactory.getLogger(EsHashPartitionTest.class);
private HashFunction hashFunction = new DjbHashFunction();
@Test
public void testHashPartition() {
int shardSize = 120;
List<Long> shards = new ArrayList<Long>();
long[] partSize = new long[shardSize];
for ( int i=0; i<shardSize; i++ ) {
shards.add((long) 0);
partSize[i] = 0;
}
for ( int i=0; i<1000000; i++ ) {
int shardId = MathUtils.mod(hash(String.valueOf(i)), shardSize);
shards.add(shardId, (long) ++partSize[shardId]);
}
for ( int i=0; i<shardSize; i++ ) {
log.debug("["+i+"] {}", partSize[i]);
}
}
public int hash(String routing) {
return hashFunction.hash(routing);
}
}
[Hash 함수 원본 코드]
/**
* This class implements the efficient hash function
* developed by <i>Daniel J. Bernstein</i>.
*/
public class DjbHashFunction implements HashFunction {
public static int DJB_HASH(String value) {
long hash = 5381;
for (int i = 0; i < value.length(); i++) {
hash = ((hash << 5) + hash) + value.charAt(i);
}
return (int) hash;
}
public static int DJB_HASH(byte[] value, int offset, int length) {
long hash = 5381;
final int end = offset + length;
for (int i = offset; i < end; i++) {
hash = ((hash << 5) + hash) + value[i];
}
return (int) hash;
}
@Override
public int hash(String routing) {
return DJB_HASH(routing);
}
@Override
public int hash(String type, String id) {
long hash = 5381;
for (int i = 0; i < type.length(); i++) {
hash = ((hash << 5) + hash) + type.charAt(i);
}
for (int i = 0; i < id.length(); i++) {
hash = ((hash << 5) + hash) + id.charAt(i);
}
return (int) hash;
}
}
- https://github.com/elasticsearch/elasticsearch/tree/master/src/main/java/org/elasticsearch/cluster/routing/operation/hash
이와 관련된 자세한 내용은 아래 링크 참고하세요.
http://www.elasticsearch.org/guide/en/elasticsearch/guide/current/routing-value.html