Split index 기능에 대해서 공식 문서에 나와 있는 내용을 그대로 테스트 해봤습니다.
(Shrink 와 Split 은 모두 Resize Action 에 해당 합니다.)
Reference)
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html
이 split index API 는 기존에 존재하는 또는 생성된 index 의 primary shard 를 신규 index 로 기존 primary shard 크기 보다 크게 split 해서 생성해 주는 역할을 합니다.
RESTful endpoint 는 _split 입니다.
근데 7.0 에서는 삭제 된다고 하니 제가 이걸 왜 쓰고 있는지 모르겠습니다.
하지만 늘 그렇듯이 Elasticsearch 에서는 기능이 없어지게 되면 대체 가능한 기능을 추가로 제공해 줍니다. :)
이 API 사용시 제일 중요한 부분은 IMPORTANT 에 잘 나와 있습니다.
The _split API requires the source index to be created with a specific number_of_routing_shards in order to be split in the future. This requirement has been removed in Elasticsearch 7.0.
※ Source index 를 생성 할때 설정을 해줘야 한다는 이야기 입니다.
그럼 문서에 나와 있는 데로 한번 돌려 보겠습니다.
하지 전에, elasticsearch 하나 띄워 놓으시고 kibana 도 띄워 놓으세요. 그래야 편하게 dev tool 이용해서 request 할 수 있겠죠.
Step 1) Preparing an index for splitting
Source index 를 생성 하는 과정이며 이 과정에서 반드시 routing shard 정보를 설정 하셔야 합니다.
PUT my_source_index
{
"settings": {
"index.number_of_shards" : 1,
"index.number_of_replicas" : 0,
"index.number_of_routing_shards" : 2
}
}
Step 2) Set read-only mode
Split 하기 전에 반드시 읽기 전용으로 반드시 설정을 하셔야 합니다. 안하시면 에러 납니다.
그럼 왜 해야 할까요?
보통 DB 마이그레이션 작업 하실때 생각을 해보시면 됩니다. :)
PUT /my_source_index/_settings
{
"settings": {
"index.blocks.write": true
}
}
문서를 자세히 보기 전까지 저 설정이 block 단위로 write 할 수 있도록 해주는 설정인 줄 알았습니다. ^^;
Step 3) Splitting an idex
이제 primary shard 를 2 개로 늘려 보겠습니다.
POST my_source_index/_split/my_target_index
{
"settings": {
"index.number_of_shards": 2,
"index.number_of_replicas" : 0
}
}
이 단계 작업을 하면서 주의 할 점은 당연한 내용이지만,
1. target index 가 없어야 겠죠.
2. source index 의 primary shard 보다 커야 겠죠.
3. factor 조건을 만족 해야 합니다.
routingNumShards % numTargetShards != 0 이면 안되구요.
if (sourceNumberOfShards < targetNumberOfShards) { // split
factor = targetNumberOfShards / sourceNumberOfShards;
if (factor * sourceNumberOfShards != targetNumberOfShards || factor <= 1) { 이면 안되구요. }
}
즉,
- 나눠서 나머지가 없어야 합니다.
- target shard 는 routing shard 보다 작거나 같아야 합니다.
아래는 factor 조건을 만족하지 않는 예시 입니다.
PUT my_source_index
{
"settings": {
"index.number_of_shards" : 1,
"index.number_of_replicas" : 0,
"index.number_of_routing_shards" : 4
}
}
PUT /my_source_index/_settings
{
"settings": {
"index.blocks.write": true
}
}
POST my_source_index/_split/my_target_index
{
"settings": {
"index.number_of_shards": 3,
"index.number_of_replicas" : 0
}
}
조건 1)
4 % 3 => 1 // 0 이 되어야 합니다.
조건 2)
assert getRoutingFactor(3, 4) >= 0
if ( 3 < 4 ) {
factor = 4 / 3; // factor = 1
if ( factor * 3 != 4 || factor <= 1) {
throw new IllegalArgumentException(.....);
}
}
혹시라도 사용하셔야 하는 분들이 계시다면 참고 하시면 되겠습니다.