Redis · Redis 7.4.11
В 2017 году Discord сам раскладывал серверы (гильдии) по шардам поиска: шард — это пара «кластер Elasticsearch + индекс». Постоянная привязка хранилась в Cassandra, а для выбора шарда под новый сервер держали в Redis sorted set: member — шард, score — его нагрузка.
Ключ shard_load, member вида es2:idx-07. Когда появляется новый сервер, нужно взять шард с наименьшим score и сразу прибавить ему 1 — иначе два сервера, пришедшие одновременно, получат один и тот же шард, а его нагрузка учтётся один раз.
При равной нагрузке берётся шард, который раньше по алфавиту — так ZRANGE упорядочивает равные score. Проверяется состояние shard_load после команд.
В работе: Раздача арендаторов по шардам, балансировка задач между воркерами, выбор наименее занятого курьера.
Источник: кейс Discord: индексация миллиардов сообщений в Elasticsearch, 2017. Условие пересказано своими словами.
Какие варианты выдадут наименее нагруженный шард и увеличат его нагрузку атомарно?
- EVAL: ZRANGE 0 0 и ZINCRBY 1 в одном скрипте
- EVAL: ZRANGE … BYSCORE LIMIT 0 1 и ZINCRBY 1
- EVAL: ZREVRANGE 0 0 и ZINCRBY 1
- EVAL: ZRANGE 0 0 и ZADD 1
- ZRANGE shard_load 0 0, а ZINCRBY — отдельным запросом из приложения