Aplicação de elasticsearch no uso de armazenamento estatístico

introdução de armazenamento

O armazenamento de objetos é amplamente utilizado em projetos atuais. É usado principalmente para armazenar recursos estáticos, como fotos, vídeos, áudio e arquivos. Basicamente, todos os fornecedores de serviços em nuvem têm armazenamento de objetos. O armazenamento de objetos geralmente é cobrado por GB por mês, como 0,098 yuan/GB/mês de Niu, 0,12 yuan/GB/mês de Ali. Por exemplo, se eu usei 30 GB no mês passado, o custo do mês passado é 30 * 0,098. Deve-se observar aqui que os 30 G usados ​​no mês passado não significam que haverá dados de 30 G no balde no final do mês passado, mas refere-se à última média A dosagem diária é de 30G. Por exemplo, Xiao Ming carregou arquivos 1G todas as manhãs no mês passado, então o uso no mês passado foi (1+2+3+...+30)/30=15.5G, e isso leva a um novo problema. Arquivos 1G todas as manhãs, Outro arquivo 1G foi excluído à tarde, então qual foi o uso de armazenamento no mês passado? Não deve ser 0, senão não é prostituição? Para evitar que os usuários se prostituam, você pode definir o uso diário como o espaço máximo de uso do balde naquele dia, então o Xiaoming carrega 1G pela manhã e exclui 1G à tarde. O espaço máximo de armazenamento para o dia é 1G, e o uso do mês é (1+1+1...+1 )/30=1G. Se você deseja calcular com precisão o espaço máximo do dia, precisa contar o uso atual quando cada arquivo é adicionado e excluído e, em seguida, obter o valor máximo em um dia. Se os requisitos não forem altos, você também pode contar o uso em intervalos. Aqui, apresento o uso de elasticsearch para contar o uso diário de armazenamento.

insira a descrição da imagem aqui

Processo Básico Estatístico

Conte o uso de armazenamento atual e armazene-o no ES a cada 30 minutos. Os campos principais são os seguintes:

ID do inquilino Tempo de estatísticas tamanho
1 2023-07-10 00:00:00 1024
1 10/07/2023 00:00:30 2024
1 2023-07-10 00:00:00 1024

Criar índice ES

PUT /bucket_size 
{
    
    
  "settings": {
    
    
    "number_of_shards": 6,
    "number_of_replicas": 0
  },
  "mappings": {
    
    
    "properties": {
    
    
      "id": {
    
    
        "type": "long"
      },
      "size": {
    
    
        "type": "long"
      },
      "tenantId": {
    
    
        "type": "long"
      },
      "time": {
    
    
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

Dados de teste

{
    
    
        "id": "1",
        "tenantId": 1,
        "size": 1024,
        "time": "2023-07-17 18:00:00"
    }
    {
    
    
        "id": "2",
        "tenantId": 1,
        "size": 2048,
        "time": "2023-07-17 19:00:00"
    }
    {
    
    
        "id": "3",
        "tenantId": 1,
        "size": 1024,
        "time": "2023-07-17 10:00:00"
    }
    {
    
    
        "id": "4",
        "tenantId": 2,
        "size": 1024,
        "time": "2023-07-17 09:00:00"
    }
    {
    
    
        "id": "5",
        "tenantId": 2,
        "size": 0,
        "time": "2023-07-17 10:00:00"
    }
    {
    
    
        "id": "6",
        "tenantId": 2,
        "size": 1024,
        "time": "2023-07-17 11:11:00"
    }

Consultar o uso diário do inquilino

Consulte os requisitos, insira o ID do locatário, hora de início e hora de término e retorne o uso diário de cada locatário dentro do horário especificado.

GET /bucket_size/_search
{
    
    
    "query": {
    
    
        "bool": {
    
    
            "must": [
                {
    
    
                    "terms": {
    
    
                        "tenantId": [
                            1,
                            2
                        ],
                        "boost": 1
                    }
                },
                {
    
    
                    "range": {
    
    
                        "time": {
    
    
                            "from": "2023-07-01",
                            "to": "2023-07-31",
                            "include_lower": true,
                            "include_upper": true,
                            "boost": 1
                        }
                    }
                }
            ],
            "adjust_pure_negative": true,
            "boost": 1
        }
    },
    "aggregations": {
    
    
        "tenantGroup": {
    
    
            "terms": {
    
    
                "field": "tenantId",
                "size": 10,
                "min_doc_count": 1,
                "shard_min_doc_count": 0,
                "show_term_doc_count_error": false,
                "order": [
                    {
    
    
                        "_count": "desc"
                    },
                    {
    
    
                        "_key": "asc"
                    }
                ]
            },
            "aggregations": {
    
    
                "groupDay": {
    
    
                    "date_histogram": {
    
    
                        "field": "time",
                        "format": "yyyy-MM-dd",
                        "calendar_interval": "1d",
                        "offset": 0,
                        "order": {
    
    
                            "_key": "asc"
                        },
                        "keyed": false,
                        "extended_bounds" : {
    
     
                            "min" : "2023-07-01",
                            "max" : "2023-07-31"
                        }

                    },
                    "aggregations": {
    
    
                        "maxSize": {
    
    
                            "max": {
    
    
                                "field": "size",
                                "missing": 0 
                            }
                        }
                    }
                }
            }
        }
    }
}

resultado

{
    
    
    "took": 3,
    "timed_out": false,
    "_shards": {
    
    
        "total": 6,
        "successful": 6,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
    
    
        "total": {
    
    
            "value": 6,
            "relation": "eq"
        },
        "max_score": 2,
        "hits": [

            {
    
    
                "_index": "bucket_size",
                "_type": "_doc",
                "_id": "2",
                "_score": 2,
                "_source": {
    
    
                    "id": "2",
                    "tenantId": 1,
                    "size": 2048,
                    "time": "2023-07-17 19:00:00"
                }
            }
        ]
    },
    "aggregations": {
    
    
        "tenantGroup": {
    
    
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
    
    
                    "key": 1,
                    "doc_count": 3,
                    "groupDay": {
    
    
                        "buckets": [
                            {
    
    
                                "key_as_string": "2023-07-01",
                                "key": 1688169600000,
                                "doc_count": 0,
                                "maxSize": {
    
    
                                    "value": null
                                }
                            },
                            {
    
    
                                "key_as_string": "2023-07-02",
                                "key": 1688256000000,
                                "doc_count": 0,
                                "maxSize": {
    
    
                                    "value": null
                                }
                            }
                        ]
                    }
                },
                {
    
    
                    "key": 2,
                    "doc_count": 3,
                    "groupDay": {
    
    
                        "buckets": [
                          
                            {
    
    
                                "key_as_string": "2023-07-31",
                                "key": 1690761600000,
                                "doc_count": 0,
                                "maxSize": {
    
    
                                    "value": null
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}

Implementação usando código JAVA

 public Map<Long, Map<String, Long>> getTenantSize(Long[] tenantIds, String mouthStartDate, String mouthEndDate) throws IOException {
    
    
        Map<Long, Map<String, Long>> map = new TreeMap<>();
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termsQuery("tenantId", Arrays.asList(tenantIds)));
        queryBuilder.must(QueryBuilders.rangeQuery("time").gte(mouthStartDate).lte(mouthEndDate));
        AggregationBuilder tenantGroup = AggregationBuilders.terms("tenantGroup").field("tenantId")
                .subAggregation(AggregationBuilders.dateHistogram("groupDay").field("time").calendarInterval(DateHistogramInterval.DAY)
                        .format(DatePattern.NORM_DATE_PATTERN).order(BucketOrder.key(true)).extendedBounds(new LongBounds(mouthStartDate,mouthEndDate))
                        .subAggregation(AggregationBuilders.max("maxSize").field("size"))
                );
        Aggregations aggregations = esClient.search(queryBuilder, tenantGroup, "bucket_size");
        Map<String, Aggregation> tenantGroupMap = aggregations.asMap();
        if (MapUtil.isNotEmpty(tenantGroupMap)) {
    
    
            tenantGroupMap.forEach((k, v) -> {
                Terms terms = (Terms) v;
                List<? extends Terms.Bucket> buckets = terms.getBuckets();
                if (CollUtil.isNotEmpty(buckets)) {
    
    
                    buckets.forEach(bucket -> {
    
    
                        Map<String, Long> daySizeMap = new TreeMap<>();
                        Map<String, Aggregation> dayGroup = bucket.getAggregations().asMap();
                        if (MapUtil.isNotEmpty(dayGroup)) {
    
    
                            dayGroup.forEach((key, value) -> {
                                ParsedDateHistogram daySizeTerms = (ParsedDateHistogram) value;
                                List<? extends Histogram.Bucket> daySizeBucket = daySizeTerms.getBuckets();
                                if (CollUtil.isNotEmpty(daySizeBucket)) {
    
    
                                    daySizeBucket.forEach(daySize -> {
    
    
                                        ParsedMax maxSize = daySize.getAggregations().get("maxSize");
                                        Long size=maxSize.getValue()!=Double.NEGATIVE_INFINITY? Double.valueOf(maxSize.getValue()).longValue():0L;
                                        daySizeMap.put(daySize.getKeyAsString(),size);
                                    });
                                }
                            });
                        }
                        map.put(Long.valueOf(bucket.getKeyAsString()), daySizeMap);
                    });

                }
            });
        }
        return map;
    }

Resumir

Este artigo apresenta principalmente o uso do armazenamento de computação elasticsearch para aprender a usar a consulta do grupo elasticsearch e usar o código JAVA para chamar a consulta do grupo elasticsearch. Existem as seguintes precauções:

  1. Se você consultar de 1º a 30 de julho, se não houver dados do dia no ES, também será retornado. Date_histogram é usado aqui, e extended_bounds é forçado a retornar null
  2. Depois que os resultados da consulta são agrupados, eles devem ser classificados por tempo
  3. De acordo com as agregações diárias, use max para obter o maior tamanho do dia como o uso de armazenamento do dia
  4. A consulta do grupo Elasticsearch consome mais memória. Ela foi agrupada em três camadas. O tempo e o número de inquilinos não devem ser muito, caso contrário, causará OOM
  5. No caso, o armazenamento é contabilizado a cada 30 minutos.Se fizer upload e deletar em 30 minutos, será prostituído.

Acho que você gosta

Origin blog.csdn.net/whzhaochao/article/details/131822058
Recomendado
Clasificación