Dimensionar um cluster do DAX - Amazon DynamoDB

Dimensionar um cluster do DAX

A capacidade e a disponibilidade totais de um cluster do DAX dependem do tipo e da quantidade de nós. Mais nós no cluster aumentam sua capacidade de leitura, mas não a capacidade de gravação. Tipos de nó maiores (até r5.8xlarge) conseguem lidar com mais gravações, mas uma quantidade pequena de nós pode afetar a disponibilidade em caso de falha em um nó. Para obter mais informações sobre como dimensionar um cluster do DAX, consulte Guia de dimensionamento de clusters do DAX.

As seções a seguir discutem os diferentes aspectos de dimensionamento que você deve considerar para equilibrar o tipo e a contagem de nós a fim de criar um cluster escalável e econômico.

Disponibilidade de planejamento

Ao dimensionar um cluster do DAX, primeiro é necessário se concentrar na disponibilidade desejada. A disponibilidade de um serviço em clusters, como o DAX, é uma dimensão do número total de nós no cluster. Como um cluster de nó único não tolera falhas, sua disponibilidade é igual a um nó. Em um cluster com dez nós, a perda de um único nó tem um impacto mínimo na capacidade geral do cluster. Essa perda não tem um impacto direto na disponibilidade porque os nós restantes conseguirão atender às solicitações de leitura. Para retomar as gravações, o DAX aponta rapidamente um novo nó primário.

O DAX é baseado em VPC. Ele usa um grupo de sub-redes para determinar em quais zonas de disponibilidade ele pode executar nós e quais endereços IP usar das sub-redes. Para workloads de produção, é altamente recomendável usar o DAX com pelo menos três nós em zonas de disponibilidade diferentes. Isso garante que o cluster tenha mais de um nó para lidar com as solicitações, mesmo em caso de falha de um único nó ou zona de disponibilidade. Um cluster pode ter até 11 nós, sendo um nó primário e dez réplicas de leitura.

Planejar o throughput de gravação

Todos os clusters do DAX têm um nó primário para solicitações do tipo write-through. O tamanho do tipo de nó do cluster determina sua capacidade de gravação. A adição de réplicas de leitura não aumenta a capacidade de gravação do cluster. Portanto, você deve considerar a capacidade de gravação durante a criação do cluster, pois não poderá alterar o tipo de nó posteriormente.

Se a aplicação precisar gravar por meio do DAX para atualizar o cache de itens, considere aumentar o uso de recursos do cluster para facilitar a gravação. As gravações no DAX consomem cerca de 25 vezes mais recursos do que as leituras de acertos de cache. Isso pode exigir um tipo de nó maior em relação a clusters somente leitura.

Para obter orientação adicional sobre como determinar se a gravação do tipo write-through ou write-around funcionará melhor para sua aplicação, consulte Estratégias para gravações.

Planejar o throughput de leitura

A capacidade de leitura de um cluster do DAX depende da taxa de acertos de cache da workload. Como o DAX lê dados do DynamoDB quando ocorre uma perda no cache, ele consome aproximadamente dez vezes mais recursos do cluster do que um acerto de cache. Para aumentar os acertos de cache, aumente a configuração de TTL do cache para definir o período durante o qual um item é armazenado no cache. No entanto, uma duração de TTL mais longa aumenta a chance de ler versões mais antigas do item, a menos que as atualizações sejam gravadas no DAX por write-through.

Para garantir que o cluster tenha capacidade de leitura suficiente, ajuste a escala do cluster horizontalmente conforme mencionado em Escalar um cluster horizontalmente. A adição de mais nós adiciona réplicas de leitura ao pool de recursos, enquanto a remoção de nós reduz a capacidade de leitura. Ao selecionar a quantidade de nós e seus tamanhos para um cluster, considere as quantidades mínima e máxima de capacidade de leitura necessária. Se você não conseguir ajustar a escala de um cluster horizontalmente com tipos de nó menores para atender aos seus requisitos de leitura, use um tipo de nó maior.

Planejar o tamanho do conjunto de dados

Cada tipo de nó disponível tem um tamanho de memória definido para que o DAX armazene os dados em cache. Se um tipo de nó for muito pequeno, o conjunto de dados de trabalho solicitado por uma aplicação não caberá na memória e resultará em perdas no cache. Como nós maiores oferecem suporte a caches maiores, use um tipo de nó maior do que o conjunto de dados estimado que você precisa armazenar em cache. Um cache maior também melhora a taxa de acertos de cache.

Você pode obter retornos decrescentes ao armazenar itens em cache com poucas leituras repetidas. Calcule o tamanho da memória para itens acessados com frequência e verifique se o cache é grande o suficiente para armazenar esse conjunto de dados.

Calcular os requisitos aproximados de capacidade do cluster

Você pode estimar as necessidades de capacidade total da sua workload para ajudar a selecionar o tamanho e a quantidade adequados de nós do cluster. Para fazer essa estimativa, calcule a variável de solicitação por segundo normalizada (RPS normalizada). Essa variável representa o total de unidades de trabalho ao qual a aplicação exige que o cluster do DAX ofereça suporte, incluindo acertos de cache, perdas no cache e gravações. Para calcular a RPS normalizada, use as seguintes entradas:

  • ReadRPS_CacheHit: especifica o número de leituras por segundo que resultam em um acerto de cache.

  • ReadRPS_CacheMiss: especifica o número de leituras por segundo que resultam em uma perda no cache.

  • WriteRPS: especifica o número de gravações por segundo que passarão pelo DAX.

  • DaxNodeCount: especifica o número de nós no cluster do DAX.

  • Size: especifica o tamanho do item que está sendo gravado ou lido em KB, arredondado para o número inteiro de KB mais próximo.

  • 10x_ReadMissFactor: representa um valor de 10. Quando ocorre uma perda no cache, o DAX usa aproximadamente dez vezes mais recursos do que em acertos de cache.

  • 25x_WriteFactor: representa um valor de 25 porque uma gravação por write-through no DAX usa aproximadamente 25 vezes mais recursos do que em acertos de cache.

Com a fórmula a seguir, você pode calcular a RPS normalizada.

Normalized RPS = (ReadRPS_CacheHit * Size) + (ReadRPS_CacheMiss * Size * 10x_ReadMissFactor) + (WriteRequestRate * 25x_WriteFactor * Size * DaxNodeCount)

Por exemplo, considere os seguintes dados de entrada:

  • ReadRPS_CacheHit = 50.000

  • ReadRPS_CacheMiss = 1.000

  • ReadMissFactor = 1

  • Size = 2 KB

  • WriteRPS = 100

  • WriteFactor = 1

  • DaxNodeCount = 3

Ao substituir esses valores na fórmula, você pode calcular a RPS normalizada conforme mostrado a seguir.

Normalized RPS = (50,000 Cache Hits/Sec * 2KB) + (1,000 Cache Misses/Sec * 2KB * 10) + (100 Writes/Sec * 25 * 2KB * 3)

Neste exemplo, o valor calculado da RPS normalizada é 135.000. No entanto, esse valor de RPS normalizada não considera a manutenção da utilização do cluster abaixo de 100% nem a perda de nós. Recomendamos que você leve em consideração uma capacidade adicional. Para fazer isso, determine o maior entre estes dois fatores de multiplicação: utilização pretendida ou tolerância à perda de nós. Depois, multiplique a RPS normalizada pelo fator maior para obter uma solicitação por segundo pretendida (RPS pretendida).

  • Utilização pretendida

    Como os impactos no desempenho aumentam as perdas no cache, não recomendamos executar o cluster do DAX com 100% de utilização. Idealmente, você deve manter a utilização do cluster igual ou inferior a 70%. Para alcançar isso, multiplique a RPS normalizada por 1,43.

  • Tolerância à perda de nós

    Se um nó falhar, a aplicação deverá ser capaz de distribuir as solicitações entre os nós restantes. Para garantir que os nós permaneçam abaixo de 100% de utilização, escolha um tipo de nó grande o suficiente para absorver tráfego extra até que o nó com falha volte a ficar on-line. Para um cluster com menos nós, cada nó deve tolerar aumentos maiores de tráfego em caso de falha em um nó.

    Se um nó primário falhar, o DAX recuperará automaticamente uma réplica de leitura e a designará como novo nó primário. Se um nó de réplica falhar, outros nós do cluster do DAX ainda poderão atender às solicitações até que o nó com falha seja recuperado.

    Por exemplo, um cluster do DAX de três nós com uma falha de nó requer uma capacidade adicional de 50% nos dois nós restantes. Isso exige um fator multiplicador de 1,5. Por outro lado, um cluster de 11 nós com falha em um nó requer uma capacidade adicional de 10% nos nós restantes, ou um fator de multiplicação de 1,1.

Com a fórmula a seguir, você pode calcular a RPS pretendida.

Target RPS = Normalized RPS * CEILING(TargetUtilization, NodeLossTolerance)

Por exemplo, para calcular a RPS pretendida, considere os seguintes valores:

  • Normalized RPS = 135.000

  • TargetUtilization = 1,43

    Como nosso objetivo é uma utilização máxima do cluster de 70%, vamos definir TargetUtilization como 1,43.

  • NodeLossTolerance = 1,5

    Digamos que estamos usando um cluster de três nós, portanto vamos definir NodeLossTolerance como 50% da capacidade.

Ao substituir esses valores na fórmula, você pode calcular a RPS pretendida conforme mostrado a seguir.

Target RPS = 135,000 * CEILING(1.43, 1.5)

Neste exemplo, como o valor de NodeLossTolerance é maior que TargetUtilization, calculamos o valor da RPS pretendida com NodeLossTolerance. Isso nos dá uma RPS pretendida de 202.500, que é a quantidade total de capacidade à qual o cluster do DAX deve oferecer suporte. Para determinar o número de nós necessários em um cluster, mapeie a RPS pretendida para uma coluna apropriada na tabela a seguir. Para este exemplo de RPS pretendida de 202.500, é necessário o tipo de nó dax.r5.large com três nós.

Aproximar a capacidade de throughput do cluster por tipo de nó

Usando a Target RPS formula, você pode estimar a capacidade do cluster para diferentes tipos de nó. A tabela a seguir mostra as capacidades aproximadas para clusters com 1, 3, 5 e 11 tipos de nó. Essas capacidades não substituem a necessidade de realizar testes de carga do DAX com padrões de solicitação e dados próprios. Além disso, essas capacidades não incluem instâncias do tipo t devido à falta de capacidade fixa de CPU. A unidade para todos os valores na tabela a seguir é a RPS normalizada.

Tipo de nó (memória) 1 nó 3 nós 5 nós 11 nós
dax.r5.24xlarge (768 GB) 1 milhão 3 milhões 5 milhões 11 milhões
dax.r5.16xlarge (512 GB) 1 milhão 3 milhões 5 milhões 11 milhões
dax.r5.12xlarge (384 GB) 1 milhão 3 milhões 5 milhões 11 milhões
dax.r5.8xlarge (256 GB) 1 milhão 3 milhões 5 milhões 11 milhões
dax.r5.4xlarge (128 GB) 600 mil 1,8 milhão 3 milhões 6,6 milhões
dax.r5.2xlarge (64 GB) 300 mil 900 mil 1,5 milhão 3,3 milhões
dax.r5.xlarge (32 GB) 150 mil 450 mil 750 mil 1,65 milhão
dax.r5.large (16 GB) 75 mil 225 mil 375 mil 825 mil

Devido ao limite máximo de 1 milhão de NPS (operações de rede por segundo) para cada nó, os nós do tipo dax.r5.8xlarge ou maiores não contribuem com capacidade adicional para o cluster. Tipos de nó maiores que 8xlarge podem não contribuir para a capacidade de throughput total do cluster. No entanto, esses tipos de nó podem ser úteis para armazenar um conjunto maior de dados de trabalho na memória.

Ajustar a escala da capacidade de gravação em clusters do DAX

Cada gravação no DAX consome 25 solicitações normalizadas em cada nó. Como há um limite de 1 milhão de RPS para cada nó, um cluster do DAX é limitado a 40.000 gravações por segundo, sem considerar o uso de leitura.

Se seu caso de uso exigir mais de 40.000 gravações por segundo no cache, você deverá usar clusters do DAX separados e fragmentar as gravações entre eles. Semelhante ao DynamoDB, você pode fazer o hash da chave de partição dos dados que está gravando no cache. Depois, utilize o cálculo de módulo para determinar em qual fragmento gravar os dados.

O exemplo a seguir calcula o hash de uma string de entrada. Depois, é calculado o módulo do valor de hash com 10.

def hash_modulo(input_string): # Compute the hash of the input string hash_value = hash(input_string) # Compute the modulus of the hash value with 10 bucket_number = hash_value % 10 return bucket_number #Example usage if _name_ == "_main_": input_string = input("Enter a string: ") result = hash_modulo(input_string) print(f"The hash modulo 10 of '{input_string}' is: {result}.")