Redis®*: Classificar utilizadores em tempo real

Aprenda a classificar 2 milhões de utilizadores por pontuação em tempo real usando Redis

👋 Bem-vindo à documentação da Stackhero!

A Stackhero oferece uma solução Redis cloud pronta a usar que proporciona uma série de benefícios, incluindo:

  • Interface web Redis Commander incluída.
  • Tamanho e transferências de mensagens ilimitados.
  • Atualizações simplificadas com apenas um clique.
  • Desempenho ótimo e segurança robusta garantidos por uma VM privada e dedicada.

Poupe tempo e simplifique a sua vida: são necessários apenas 5 minutos para experimentar a solução de hospedagem Redis cloud da Stackhero!

Um dos nossos clientes contactou-nos com um desafio interessante. Ele gere um site desportivo onde os utilizadores ganham pontos quando ganham apostas ou completam várias ações.

O seu objetivo era mostrar a classificação de cada utilizador, exibir os utilizadores imediatamente acima e abaixo deles, e gerar uma tabela dos 100 melhores. Com uma comunidade de 2 milhões de utilizadores, os dados precisavam de ser processados em tempo real!

Na Stackhero adoramos enfrentar desafios como este. Neste artigo, vamos guiá-lo através da nossa solução passo a passo.

Bases de dados tradicionais como MySQL, PostgreSQL ou Elasticsearch não são concebidas para tarefas de classificação de baixa latência. Isto levou-nos a explorar outra opção.

Selecionámos Redis, uma base de dados em memória extremamente rápida e fiável. De acordo com DB-Engines, é a 7ª base de dados mais utilizada no mundo e a principal opção na categoria "Key-value store".

Redis oferece múltiplos modelos de dados. Para este cenário, destaca-se um: os "sorted sets".

Os sorted sets combinam uma chave e uma pontuação. No nosso caso, a chave é o ID do utilizador e a pontuação representa os pontos do utilizador.

Começámos por lançar um serviço Redis na Stackhero. O serviço está ativo em apenas 2 minutos com a última versão estável, oferece faturação por hora e possui o Redis Commander, uma interface web prática. Validámos o conceito usando esta interface.

Adicionámos três utilizadores com IDs e pontuações de exemplo como mostrado abaixo:

| Nome de Utilizador | Pontuação | | - | - | | userId1 | 11 | | userId2 | 54 | | userId3 | 24 |

Estes utilizadores foram adicionados a um sorted set chamado usersScores usando os seguintes comandos Redis:

ZADD usersScores 11 "userId1"
ZADD usersScores 54 "userId2"
ZADD usersScores 24 "userId3"

Redis Commander, a interface web fornecida na Stackhero com instâncias RedisRedis Commander, a interface web fornecida na Stackhero com instâncias Redis

Em seguida, recuperámos a pontuação de userId1:

ZSCORE usersScores "userId1"
> 11

Isto confirmou que a pontuação para userId1 era de facto 11. Depois disso, verificámos a classificação de userId1:

ZREVRANK usersScores "userId1"
> 2

Lembre-se, a classificação começa em 0. Isto significa que as classificações são as seguintes:

| Nome de Utilizador | Pontuação | Classificação | | - | - | - | | userId1 | 11 | 2 | | userId2 | 54 | 0 | | userId3 | 24 | 1 |

O comando ZREVRANK retornou 2, que é exatamente o que esperávamos para userId1.

Também pode obter as entradas principais. Por exemplo, para recuperar os primeiros 2 utilizadores (da classificação 0 à classificação 1) execute:

ZREVRANGE usersScores 0 1 WITHSCORES
> 1) userId2
> 2) 54
> 3) userId3
> 4) 24

Para obter os 100 melhores utilizadores, basta executar:

ZREVRANGE usersScores 0 99 WITHSCORES

Esta abordagem é eficiente e perfeitamente adequada para classificação em tempo real de alto desempenho.

Abaixo estão alguns comandos Redis adicionais usados no site do nosso cliente:

  • Obter utilizadores classificados entre as posições 50 e 100: ZREVRANGE usersScores 50 100 WITHSCORES
  • Adicionar um utilizador: ZADD usersScores 40 "userId4"
  • Atualizar a pontuação de um utilizador (isto substitui a entrada existente userId4): ZADD usersScores 42 "userId4"
  • Remover um utilizador: ZREM usersScores "userId4"

Após validar o conceito no Redis Commander, é hora de integrar o Redis em código real. O nosso cliente usa Node.js e abaixo está um exemplo usando ioredis como cliente:

const Redis = require('ioredis');

(async () => {
  // Definir credenciais Redis
  // Se usar Stackhero, encontrará estas no painel de controlo Stackhero
  const redis = new Redis({
    host: '<redisServerHost>',
    password: '<redisServerPassword>',
    port: <PORT_TLS>, // <PORT_CLEAR> é para conexões não seguras e <PORT_TLS> é para TLS. TLS deve ser usado.
    tls: {}, // Fornecer um objeto vazio para ativar TLS
    lazyConnect: true
  });

  // Conectar ao Redis
  await redis.connect();

  // Adicionar utilizadores
  await redis.zadd('usersScores', 11, 'userId1');
  await redis.zadd('usersScores', 54, 'userId2');
  await redis.zadd('usersScores', 24, 'userId3');

  // Recuperar pontuação de userId1
  const score = await redis.zscore('usersScores', 'userId1');
  console.log('userId1 tem ' + score + ' pontos');

  // Recuperar posição de classificação de userId1
  const rankPosition = await redis.zrevrank('usersScores', 'userId1');
  console.log('userId1 está classificado na posição ' + rankPosition);

  // Desconectar do Redis
  await redis.disconnect();
})();

Este simples mas poderoso trecho de código é ideal para gerir dados de classificação em tempo real.

Enfrentar este problema foi tanto interessante quanto desafiador. No nosso caso, Redis provou ser uma solução ideal porque é fácil de usar, poderoso e excepcionalmente rápido.

Se gostaria de experimentar com Redis, pode iniciar uma instância na Stackhero em apenas 2 minutos. Desfrute da última versão estável, uma interface web, backups e desempenho impressionante ao seu alcance.

Painel de controlo Stackhero mostrando serviços Node.js e Redis em execuçãoPainel de controlo Stackhero mostrando serviços Node.js e Redis em execução