Статьи

Решение проблемы с суперузлами

 В теории графов и сетевых науках «суперузел» — это вершина с непропорционально большим числом ребер инцидентности. Хотя суперузлы редки в естественных графах (как это продемонстрировано статистически для степенных распределений степеней), они часто обнаруживаются во время анализа графов. Причина в том, что суперузлы связаны с таким количеством других вершин, что они существуют на многочисленных путях в графе. Следовательно, произвольный обход может касаться суперузла. В графических вычислениях суперузлы могут привести к проблемам с производительностью системы. К счастью, для графов свойств существует теоретическое и прикладное решение этой проблемы.

Супер-узлы в реальном мире

Одноранговый обмен файлами

На рубеже тысячелетий обмен файлами в Интернете поддерживался такими службами, как Napster и Gnutella . В отличие от Napster, Gnutella — это настоящая одноранговая система, в которой нет центрального индекса файлов. Вместо этого поиск клиента отправляется соседним клиентам. Если у этих клиентов нет файла, то запрос распространяется на соседние клиенты, и так далее, и так далее. Как и в любом естественном графе, суперузел находится всего в нескольких шагах. Поэтому во многих одноранговых сетях клиенты суперузлов быстро заполняются поисковыми запросами, и, в свою очередь, выполняется DoS .

Социальная сеть знаменитостей

У президента Барака Обамы в настоящее время есть 21 322 866 подписчиков в Твиттере . Когда Обама пишет в Твиттере, этот твит должен регистрироваться в потоках активности более 21 миллиона аккаунтов. Вершина Барака Обамы считается суперузлом. В качестве противоположного примера, когда Стивен Маллет пишет в Твиттере , нужно обновить только 59 потоков. Твиттер осознает это несоответствие и поддерживает различные механизмы для обработки «Обам» (то есть знаменитостей) и «Стефанов» (то есть плебеев) сферы Twitter.

Чертежи и Вершинные Запросы

Blueprints — это Java-интерфейс для графического программного обеспечения. Различные графические базы данных , графические движки в памяти и платформы пакетной аналитики используют Blueprints. В июне 2012 года был выпущен Blueprints 2.x с поддержкой « вершинных запросов ». Вершинный запрос лучше всего объяснить на примере.

Предположим, что есть вершина с именем Dan. Инцидент с Дэном составляет 1110 ребер. Эти ребра обозначают людей, которых Дан знает (10 ребер), что ему нравится (100 ребер) и твиты, которые он написал (1000 ребер). Если Дану нужен список всех людей, которых он знает, и границы инцидентов не индексируются по меткам, то Дэну придется пройти через все 1110 границ, чтобы найти 10 человек, которых он знал. Однако, если ребра Дэна индексируются по метке ребра, то поиск в хэше knowsсразу даст 10 человек — O(n)против O(1), где nчисло ребер, инцидентных Дэну.

Идея разделения ребер с помощью различающихся качеств может стать шагом вперед в графах свойств . Графики свойств поддерживают пары ключ / значение на вершинах и ребрах. Например, knows-edge может иметь -property typeс возможными значениями «работа», «семья» и «избранное» и sinceсвойство, указывающее, когда начались отношения. Точно так же likes-edges может иметь свойство от 1 до 5, ratingа tweet-edges может иметь timeштамп, обозначающий, когда твит был твитнут. Blueprints ‘ Queryпозволяет разработчику указывать ограничения на инцидентных краях, которые будут получены. Например, чтобы получить все предметы с высокой оценкой Дэна, оценивается следующий код Blueprints.

dan.query().labels("likes").interval("rating",4,6).vertices()

Титан и вершинно-ориентированные индексы

Blueprints предоставляет только интерфейс для представления вершинных запросов. Это зависит от базовой системы графов, чтобы использовать указанные ограничения в своих интересах. База данных распределенных графов Titan широко использует вершинно-ориентированные индексы для детального извлечения краевых данных как с диска, так и из памяти. Чтобы продемонстрировать эффективность этих индексов, предоставляется эталонный тест с использованием Titan / BerkeleyDB ( ACID- вариант Titan — см. Обзор хранилища Titan ).

10 экземпляров Titan / BerkeleyDB создаются с использованием вершины человека по имени Dan. 5 из этих экземпляров имеют вершинно-ориентированные индексы, а 5 — нет. Каждый из 5 экземпляров каждого типа имеет переменное число ребер, инцидентных Дану. Эти цифры приведены ниже.

общее количество инцидентов knows-ребра likes-ребра tweets-ребра
111 1 10 100
+1110 10 100 1000
11100 100 1000 10000
111000 1000 10000 100000
1110000 10000 100000 1000000

Гремлин скрипт / Groovy для создания вышеупомянутых звездных графиков приведен ниже, где iпеременная определения размера результирующего графика.

g = TitanFactory.open('/tmp/supernode')
// index configuration snippet goes here for Titan w/ vertex-centric indices
g.createKeyIndex('name',Vertex.class)
g.addVertex([name:'dan'])
  
r = new Random(100)
types = ['work','family','favorite']
(1..i).each{g.addEdge(g.V('name','dan').next(),g.addVertex(),'knows',[type:types.get(r.nextInt(3)),since:it]); stopTx(g,it)}
(1..(i*10)).each{g.addEdge(g.V('name','dan').next(),g.addVertex(),'likes',[rating:r.nextInt(5)]); stopTx(g,it)}
(1..(i*100)).each{g.addEdge(g.V('name','dan').next(),g.addVertex(),'tweets',[time:it]); stopTx(g,it)}

Для 5 экземпляров Titan / BerkeleyDB
с вершинно-ориентированными индексами был проанализирован следующий фрагмент кода. Этот код определяет индексы (см. Конфигурации типов Titan
).

type = g.makeType().name('type').simple().functional(false).dataType(String.class).makePropertyKey()
since = g.makeType().name('since').simple().functional(false).dataType(Integer.class).makePropertyKey()
rating = g.makeType().name('rating').simple().functional(false).dataType(Integer.class).makePropertyKey()
time = g.makeType().name('time').simple().functional(false).dataType(Integer.class).makePropertyKey()
g.makeType().name('knows').primaryKey(type,since).makeEdgeLabel()
g.makeType().name('likes').primaryKey(rating).makeEdgeLabel()
g.makeType().name('tweets').primaryKey(time).makeEdgeLabel()

Далее представлены три обхода, основанные на Дэне. Первый получает всех людей, которых Дэн знает о конкретном случайно выбранном типе (например, члены семьи). Второй возвращает все то, что Дэн высоко оценил (то есть 4 или 5 звезд). Третий возвращает 10 последних твитов Дэна. Наконец, обратите внимание, что Gremlin компилирует каждое выражение в соответствующий вершинный запрос (см. Оптимизацию обхода Gremlin
).

g.V('name','dan').outE('knows').has('type',types.get(r.nextInt(3)).inV
g.V('name','dan').outE('likes').interval('rating',4,6).inV
g.V('name','dan').outE('tweets').has('time',T.gt,(i*100)-10).inV

Приведенные выше обходы выполнялись по 25 раз, при этом база данных перезапускалась после каждого запроса, чтобы продемонстрировать время отклика с холодными
JVM- кэшами. Обратите внимание, что время отклика в оперативной памяти в оперативной памяти показывает схожую картину (хотя и относительно быстрее) Усредненные результаты представлены ниже, где ось Y находится в
логарифмическом масштабе . Зеленый, красный и синий цвета обозначают первый, второй и третий запросы соответственно. Более того, есть светлая и темная версия каждого цвета. Облегченная версия — Titan / BerkeleyDB
без вершинно-ориентированных индексов, а темная версия — Titan / BerkeleyDB
с вершинно-ориентированными индексами.

Возможно, самый впечатляющий результат — поиск 10 самых последних твитов Дэна (синий). С вершинно-ориентированными индексами (темно-синим), когда число твитов Дэна увеличивается до 1 миллиона, время, необходимое для получения первых 10, остается постоянным на уровне около 1,5 миллисекунд. Без индексов этот запрос растет пропорционально объему данных и, в конечном итоге, для его завершения требуется 13 секунд (светло-синий). Это разность времени отклика на 4 порядка для одного и того же набора результатов . Этот пример демонстрирует, насколько полезны вершинно-ориентированные индексы для систем типа потока операций.

На графике справа отображается количество вершин, возвращаемых каждым запросом, для каждого размера графика. Как и ожидалось, число tweetsостается постоянным на уровне 10, в то время как количество извлеченных вершин knowsи likesвершин увеличивается пропорционально растущим графам. Хотя примеры на одном и том же графике (с индексами и без них) возвращают одни и те же данные, доступ к этим данным быстрее с вершинно-ориентированными индексами.

Наконец, Titan также поддерживает составные ключевые индексы. Фрагмент графика строительства код предыдущие правопреемников первичный ключ как typeи sinceв knows-ребра. Таким образом, поиск 10 последних сотрудников Дэна более эффективен, чем получение в память всех сотрудников Дэна и последующая сортировка since. Заинтересованный читатель может исследовать время выполнения таких составных вершинно-ориентированных запросов, дополняя предоставленные фрагменты кода.

Вывод

Суперузел является проблемой, только когда игнорируется различающая информация между ребрами. Если все ребра обрабатываются одинаково, то O(n)требуется линейный поиск по множеству падающих ребер вершины. Однако , когда индексы и порядок сортировки используются, O(log(n))и O(1)поиски могут быть достигнуты. Представленные результаты демонстрируют в 2-5 раз более быстрый поиск для представленных knows/ likesзапросов и до 10 000 раз быстрее для tweetsзапроса при использовании вершинно-ориентированных индексов. Теперь рассмотрим, когда обход больше одного прыжка. Среды выполнения объединяются комбинаторным образом. Составление в 1 миллисекунду против 10 секунд приводит к астрономическим различиям в общем времени прохождения.

Графическая база данных Titan может масштабироваться для поддержки сотен миллиардов ребер (через Apache Cassandra и HBase ). В таких массивных графах часто встречаются вершины с миллионами + инцидентных ребер. В мире больших графических данных важно эффективно хранить и извлекать данные с диска и из памяти. При использовании Titan фильтрация краев опускается до уровня диска, поэтому только необходимые данные фактически извлекаются и заносятся в память. Вершинно-ориентированные запросы и индексы преодолевают проблему суперузлов, интеллектуально используя метку и информацию о свойствах ребер, падающих на вершину.

Связанные материалы

Родригес, М.А., Бройчелер, М., « Титан: рост больших графовых данных », публичная лекция в Jive Software, Пало-Альто, 2012.

Broecheler, M., LaRocque, D., Rodriguez, MA, « Титан предоставляет данные больших графиков в реальном времени », блог Aurelius, август 2012 г.

Авторы

Матиас БрохелерМарко А. Родригес