Как правильно установить хэш-теги для ключа uuid, хранящегося в виде массива байтов в Redis

Согласно документации Redis хэштеги можно использовать для принудительного назначения ключей одному и тому же хеш-слоту. У меня есть вариант использования, когда мы храним {UUID}Integer как массив байтов в Redis, и я ожидаю, что для назначения хеш-слота будет использоваться только часть UUID. Проблема, с которой мы сталкиваемся, заключается в том, что если UUID содержит символы 7b или 7d, он конфликтует с { и }, представленными значениями байтов ASCII 123 (0x7b) и 125 (0x7d) соответственно, что влияет на распределение этих ключей.

Например, 7d3e4567-e89b-12d3-a456-426614174000 печатается как {}>Eg\xe8\x9b\x12\xd3\xa4VBf\x14\x17@\x00} при сохранении с хэштегами в Redis.

Есть ли способ экранировать символы в UUID, чтобы расчет хеш-слота работал правильно, или есть ли другой обходной путь?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
0
0
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Невозможно сообщить Redis, что байт 7b или 7d не является фигурной скобкой.

Единственный способ обойти эту проблему, который я вижу, — это по-другому закодировать UUID.

Я предполагаю, что вас волнует скорость кодирования и потребление памяти. В настоящее время вы используете 16 байт на UUID, что является оптимальным.

Вы можете использовать кодировку Base64, чтобы избежать этой проблемы. для этого потребуется один байт на 6 бит, следовательно, 22 байта на UUID.

Другой вариант — использовать собственную кодировку: каждые 7 бит преобразуются в символ 00..81, кроме 7b и 7d. Кодировка относительно проста — вам придется извлекать по 7 бит за раз и заменять 7b на 80 и 7d на 81. Для этого потребуется один байт на 7 бит, следовательно, 19 байт на UUID.

Другая возможная кодировка — добавление 2 байтов к UUID. Теперь у вас есть 16 байт + 16 бит. Установите эти 16 бит четности на 0. Далее для каждого из 16 байтов: если это 7b — замените его на 7a и установите соответствующий бит четности. Если это 7d — замените его на 7c и установите соответствующий бит четности. Однако с этой кодировкой есть проблема: два добавленных байта могут стать 7b или 7d. Чтобы этого избежать — вместо этого добавьте 3 байта и разделите 16 бит четности между этими 3 байтами, избегая наиболее значимого бита каждого из этих байтов. Вы можете дополнительно оптимизировать: для каждого байта UUID: if (byte & 0x01 == 0) { byte |= 1; установить соответствующий бит четности }

Более сложные кодировки могут уменьшить это число до 17 байт на UUID, но вычисление будет медленнее.

Еще один вариант, который следует рассмотреть: если вы генерируете эти UUID, вы можете просто избежать создания UUID, содержащих 7b и 7d.

Да, цель состоит в оптимизации памяти, что является причиной хранения UUID в двоичном виде. Изучение пользовательской кодировки для решения проблемы.

Ishank Gulati 29.08.2024 07:45

Если байты четности — это последние два байта ключа, то даже если дополнительные байты разрешаются в 7b или 7d, это не должно быть проблемой, верно, потому что Redis уже оценил бы хэштеги вокруг UUID? Redis использует первое вхождение согласно документации .

Ishank Gulati 30.08.2024 16:24

Нет, байты четности должны быть частью вашего закодированного UUID.

Lior Kogan 30.08.2024 19:48

На самом деле да. Вы можете хешировать только закодированный UUID без байтов четности. Некоторые UUID будут хэшироваться в один и тот же слот, но что с того? это произойдет в любом случае. Это не добавило бы существенного смещения распределения.

Lior Kogan 31.08.2024 07:15

Другие вопросы по теме