Недавно я опротестовал собеседование, плохо ответив на простой вопрос: как сайты, такие как LinkedIn, эффективно показывают расстояние отношений (1/2/3/3) от вас до каждого человека, отображаемого на странице (например, в результатах поиска людей, списке людей, работающих в компании и т.д.)?
<EDIT> Я получил существенный "трюк" решения: найти "расстояние от меня" является общей операцией (например, 20x + на одной странице, 100 сеансов входа), поэтому вы можете сделать часть "расстояние от меня до X", кешировать его, а затем повторно использовать этот кешированный частичный результат много раз, чтобы сделать другие операции намного дешевле. Я также догадался, что частичный результат, вероятно, будет моим подключением второго уровня, потому что "кеш всех подключений третьего уровня" будет слишком дорогостоящим в ОЗУ и ЦП. </EDIT>
Но, пытаясь преобразовать это понимание в решение, я придумал неувядающий ответ, связанный с созданием постоянных кэшей 2-го уровня соединений всех на сайте (что было бы чрезвычайно серьезным в перфомансе и сложным для поддержания) и я взял необъяснимый обход в использование Bloom Filters таким образом, который не имел технического смысла. Я бы не нанял себя после такого ответа!
Позже, когда я подумал о проблеме без давления интервью, нависшего над моей головой, я подошел к более разумному ответу.
-
Создайте очень быстрый способ получить соединения первого уровня для каждой из партиций идентификаторов пользователей (размер партии до ~ 1000?). Вероятно, это означает выделенный кластер серверов с множеством ОЗУ, который может кэшировать все сетевые соединения 1-го уровня в памяти. К счастью, 50M членов x сред. 100 подключений на одного члена x 4 байта на одного члена ID = < 25 ГБ для кэширования в ОЗУ, что можно выполнить с использованием недорогого оборудования. И количество изменений в день будет меньше 1%, поэтому сохранить актуальность кэша не так уж сложно. (Обратите внимание, что реляционная база данных, вероятно, будет плохим выбором для реализации этого кеша, потому что шаблон доступа "много случайных ввода-вывода" убивает производительность реляционных БД.)
-
когда пользователь входит в систему, кэширует свои соединения 2-го уровня, выбирая соединения 1-го уровня каждого подключения 1-го уровня и вставляя хэш-таблицу (ключ = идентификатор второго уровня, value = массив 1-го уровня, которые соединяют вас). Также кешируйте свои соединения первого уровня, чтобы вы могли отступить как на 1-й, так и на 2-й уровень за счет одного обратного вызова на ваш сервер удаленного кеша. Идентификаторы пользователей легко разделяются на разделы, поэтому распределенный кеш, такой как memcached, может хорошо работать для этого.
-
для любого идентификатора пользователя, чтобы узнать, находится ли он в вашей "сети" и какое отношение к вам (1-й, 2-й, 3-й), выполните следующие действия:
- Если идентификатор находится в ваших соединениях первого уровня, остановитесь.
- попробуйте найти идентификатор в кэшированных хэш-таблицах соединений 2-го уровня. Если найдено, верните массив подключений, которые свяжут вас.
- выберите идентификаторы первого уровня и повторите шаг №2 для каждого из них. Совокупность всех результатов в один массив и их возврат.
- <EDIT> в пакетную реализацию ( "найдите расстояние от меня до N разных пользователей" ), чтобы вы могли получить все удаленные результаты с шага № 3 без необходимости делать N удаленных вызовов. </EDIT>
Но я уверен, что на этот счет есть лучшие ответы. Что твое? Если вам нужен дополнительный вызов, попробуйте моделировать ситуацию inteview (не можете искать решения в Интернете).
Обратите внимание, что вопрос касался оптимального решения, независимо от того, как LinkedIn на самом деле делает это сегодня, и я посмотрел после того, как написал свой собственный ответьте выше.