Хранение и поиск через Redis Hash - PullRequest
3 голосов
/ 22 апреля 2020

У меня около 10 миллионов + пользователей с электронной почтой и телефонами. Оба указывают на идентификатор пользователя. Я создал 2 Хэша. Один для электронной почты, а другой для телефонных номеров, таких как

//A single user with Both Email and Phone number pointing to same User ID
$redis->hSet('email-users', 'abc@xyz.com', 1);
$redis->hSet('phone-users', '+192938384849', 1);

Теперь, когда вокруг миллионы пользователей, Hash становится перегруженным, и я также хочу искать по этим хэшам. Как я хочу получить идентификатор пользователя из электронной почты от пользователей электронной почты ha sh.

Поскольку я обнаружил, что хеши должны поддерживаться с ZipList на Redis - лучший способ сохранить большую карту ( словарь) и разделен на меньшие сегменты фиксированного размера, скажем, максимум 10000 ключей в одном га sh.

Итак, если я разделю свои 10 миллионов пользователей на сегменты по 10000 ключей, будет около 1000 хэшей для электронных писем и 1000 для телефонных номеров.

Мои вопросы: стоит ли разделять пользователей на эти 1000 сегментов? и если да, то как я могу найти эти 1000 ведер? Или есть лучшая альтернатива?

PS Я использую PHP и получаю через них все 1000 хешей и l oop, что может быть довольно ресурсоемким, и я боюсь, что использование неправильного подхода приведет к также убивают фактическую производительность Redis Power.

Просто для заметки, я думаю, что мы можем создать некоторый алгоритм, такой как libketama, для согласованного хеширования для размещения ключей на случайных серверах.

Кроме того, если сложно работать с алфавитами, мы можем сначала преобразовать каждое письмо в числа, такие как a = 1, b = 2, c = 3 ... z = 26 с добавлением 0 (ноль) для создания это уникально и + s для @ и. персонажи. Например,

abcd@gmail.com  ->  10203040+901301090+3015013

Итак, теперь у нас есть числа, которые облегчают применение любых вычислений.

Ответы [ 2 ]

3 голосов
/ 22 апреля 2020

что вы можете сделать, это распределение букв и цифр в соответствии с первой или первой парой букв / цифр.

вы можете создавать свои хэши следующим образом; электронная почта первое письмо, номер телефона первая или первые две цифры

  • email-users-a
  • email-users-b
  • email-users- c
  • phone-users-10
  • phone-users-11

пока вы выполняете hset / hget, вы делаете это на уровне кода.

Редактировать:

Допустим, мы будем использовать first two digits для телефонных номеров и first two letters для электронной почты;

, тогда у нас будут такие ключи, как следующие:

  • email-users-aa
  • email-users-ab
  • phone-users-11
  • phone-users-12

Когда у нас будет электронное письмо типа ersoy@gmail.com, тогда мы будем go to er email ha sh группа, которая будет email-users-er и выполнит hget email-users-er ersoy@gmail.com.

Когда у нас есть номер телефона, такой как 123456789, тогда мы будем go до 12 звонить по номеру ha sh, который равен phone-users-12, и выполнять hget phone-users-12 123456789.

1 голос
/ 24 апреля 2020

Мои вопросы: Должен ли я разделить своих пользователей на эти 1000 групп? и если да, то как я могу найти эти 1000 ведер? Или есть лучшая альтернатива?

Да. Подход может работать следующим образом.

В этом примере давайте будем рассматривать как номера телефонов, так и идентификаторы электронной почты как строки.

Допустим, у вас есть следующие сегменты (Redis Ha sh):

For Email Ids: email_0001, email_0002, ..., email_1000
For Phone Numbers: phone_0001, phone_0002, ..., phone_1000
  1. По идентификатору электронной почты определите интервал (максимум 1000) хэширование идентификатора электронной почты. Вы можете использовать последовательное хеширование для этой цели. Теперь добавьте ключ и значение в соответствующее «ведро».

    $ HSET "email_0032" "abc@xyz.com" "UID_987"
    
  2. Повторите шаг 1 для телефонных номеров. Это избавляет вас от необходимости выполнять бухгалтерию, какой ключ входит в какое ведро. При одинаковом ключе ha sh всегда будет давать одно и то же значение, возвращая, таким образом, один и тот же номер корзины.

    $ HSET "phone_0091" "+192938384849" "UID_987"
    
  3. Чтобы получить значение, сначала найдите корзину, хэшируя email / phone, а затем ищем значение в соответствующем сегменте.

    $ HGET "phone_0091" "+192938384849"
      UID_987
    
import java.nio.charset.Charset;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;

public class Sample {

    private static final int BUCKET_SIZE = 1000;
    private static final HashFunction hashFunction = Hashing.murmur3_128();
    private static final Charset UTF8 = Charset.forName("UTF-8");

    private Sample() {
    }

    public static int pickBucket(String key, int buckets) {
        int bucket = com.google.common.hash.Hashing.consistentHash(hashFunction.hashString(key, UTF8).asLong(), buckets);
        return bucket;
    }

    private static void getFromRedisHash(String key) {

        int bucket = pickBucket(key, BUCKET_SIZE);
        // Get From Redis based on the bucket number
    }

    public static void main(String[] args) {

        System.out.println(pickBucket("abc@xyz.com", BUCKET_SIZE));
        System.out.println(pickBucket("+192938384849", BUCKET_SIZE));
    }
}

Приведенный выше пример находится в Java, я предполагаю, что PHP будет иметь аналогичный библиотеки для хеширования.

...