Оригинальная ссылка:Джей Чен, Цао Цао/Redis/2018/…
Автор: Джей Чен
Что такое «фильтр Блума»
Фильтр Блума — это волшебная структура данных,Может использоваться для определения того, находится ли элемент в наборе. Очень распространенной функцией является использованиедедупликация. Общее требование в Crawlers: есть тысячи целевых URL-адресов веб-сайтов. Как судить, был ли любимым гусеником URL? Проще говоря, каждый раз, когда гусеничный узел собирает URL, он хранит URL в базе данных, и каждый раз приходит новый URL, он отправляется в базу данных, чтобы проверить, было ли она доступна.
select id from table where url = 'https://jaychen.cc'
Однако по мере того, как поисковые роботы сканируют все больше и больше URL-адресов, к базе данных необходимо обращаться один раз перед каждым запросом, и эффективность SQL-запросов для таких строк невелика. В дополнение к базе данных, использование структуры наборов Redis также может удовлетворить эту потребность, и производительность выше, чем у базы данных. Но у Redis тоже есть проблема: он потребляет слишком много памяти. На этот раз фильтр Блума вышел очень горизонтально: этот вопрос привел меня сюда.
По сравнению с базами данных и Redis использование фильтров Блума позволяет избежать проблем с производительностью и использованием памяти.
Фильтр Блума по сути являетсябитовый массив, битовый массив состоит в том, что каждый элемент массива занимает только 1 бит. Каждый элемент может быть только 0 или 1. Применение битового массива из 10 000 элементов таким образом занимает всего 10 000 / 8 = 1250 байт пространства. Фильтр Блума имеет K хэш-функций в дополнение к битовому массиву. При добавлении элемента в фильтр Блума выполняются следующие операции:
- Выполните K вычислений для значения элемента, используя K хэш-функций, в результате чего получите K хэш-значений.
- В соответствии с полученным хеш-значением установите значение соответствующего индекса в 1 в битовом массиве.
Например 🌰 предположим, что фильтр Блума имеет 3 хэш-функции: f1, f2, f3 и битовый массивarr
. теперь кhttps://jaychen.cc
Вставьте в фильтр Блума:
- Хешируйте значение три раза, чтобы получить три значения n1, n2, n3.
- Присвойте трем элементам arr[n1], arr[n2], arr[3] битового массива значение 1.
Когда необходимо определить, находится ли значение в фильтре Блума, снова хешируйте элемент и после получения значения оцените, равен ли каждый элемент в битовом массиве 1. Если значение равно 1, это означает, что значение находится в Если в фильтре есть значение, отличное от 1, это означает, что элемент не входит в фильтр Блума.
Если вам не понятен текст, посмотрите иллюстрацию соул-артиста ниже👇👇👇
После прочтения вышеприведенного описания неизбежно возникнет вопрос: когда вставлено больше элементов, чем больше позиций в битовом массиве устанавливается в 1, когда элемент, которого нет в фильтре Блума, после вычисления хэша, результирующее значение запрашивается в битовом массиве, и возможно, что эти позиции также установлены в 1. Такой несуществующий фильтр Блума также может быть ошибочно принят за фильтр Блума. Но если фильтр Блума определяет, что элемента нет в фильтре Блума, то значение не должно быть в фильтре Блума. Проще говоря:
- Фильтры Блума говорят о наличии определенного элемента, который может быть неверно оценен.
- Фильтр Блума говорит, что элемент отсутствует, значит, он должен отсутствовать.
Недостаток этого фильтра Блума заключается в требованиях вышеуказанного поискового робота. Могут быть некоторые URL-адреса, которые не были посещены, которые могут быть ошибочно оценены как посещенные, но если это посещенный URL-адрес, он не будет ошибочно оценен как непосещенный. посетил. .
Фильтры Блума в Redis
В Redis добавлена функция модуля в версии 4.0. Фильтры Блума могут быть добавлены в Redis в виде модулей, поэтому с помощью Redis версии выше 4.0 можно загрузить, загрузивmoduleиспользовать фильтр Блума в Redis. Но это не самый простой способ, с помощью docker можно испытать фильтры блума прямо в Redis.
> docker run -d -p 6379:6379 --name bloomfilter redislabs/rebloom
> docker exec -it bloomfilter redis-cli
Фильтр Блума Redis в основном имеет две команды:
-
bf.add
Добавьте элементы в фильтр Блума:bf.add urls https://jaychen.cc
. -
bf.exists
Проверьте, находится ли элемент в фильтре:bf.exists urls https://jaychen.cc
.
Как упоминалось выше, в фильтре Блума есть ошибка, в redis есть два значения, которые определяют точность фильтра Блума:
-
error_rate
: Разрешает частоту ошибок фильтра Блума.Чем меньше значение, тем больше размер битового массива фильтра и больше занимаемое пространство. -
initial_size
: количество элементов, которые может хранить фильтр Блума. Когда фактическое количество сохраненных элементов превышает это значение, точность фильтра снижается.
В Redis есть команда для установки этих двух значений:
bf.reserve urls 0.01 100
Значение трех параметров:
- Первое значение — это имя фильтра.
- Второе значение
error_rate
значение . - Третье значение
initial_size
значение .
Одна вещь, которую следует учитывать при использовании этой команды:Имя фильтра не должно существовать до выполнения этой команды, если оно существует до выполнения этой команды, будет сообщено об ошибке:(error) ERR item exists