Mapreduce был анонсирован разработчиками Google

За последние годы проблема обработки больших массивов данных (Big Data) для мировых гигантов информационного пространства (Google, Fb, Alibaba etc.) вышла на передний план. Сервисы, предоставляемые крупными «поисковиками», социальными сетями, e-ритейлерами и другими обработчиками больших потоков информации перестали удовлетворять совершенствующимся стандартам качества (скорости обработки и хранения данных). Более того, проблема усугубляется ростом объемов, представленных к обработке, роста скорости обработки, требуемой рынком и увеличения информационного разнообразия, затрудняющего провайдерам использовать стандартные методы в алгоритмах обработки.

Согласно отчету McKinsey Institute «Большие данные – новый рубеж для инноваций, конкуренции и производительности», а аналитики TadInvest’a оценили CAPEX на разработку технологий работы с BigData в 34 млрд долл. за 2013 год. Все это подчеркивает актуальность методов и средств обработки больших массивов данных не только для списка 10-ти наиболее ликвидных мировых компаний TMT-сектора, но и для рядовых компаний-разработчиков программного обеспечения, «стремящихся на свет «голубого океана».

Google TechTalk: «MapReduce», Д.Павлов

«Большие данные» или BigData можно представить в виде набора структурированной и не структурированной информации, «пакетно» организованной, размер которой превосходит возможности типичных БД (баз данных) по занесению, хранению, управлению и анализу информации. Другими словами, Big Data – это проблема для компаний, связанных с большими объемами данных. Проблему можно рассмотреть в трех проекциях: Volume – нестандартный объем данных, Velocity – высокие минимальные показатели скорости обработки информации и Variety – многообразие информации и отсутствие структурированности. От года к году BigData «растет» в каждой из этих проекций, что заставляет провайдеров уделять больше внимания на разработку технологий работы с данными.

Быстрая обработка петабайтов неструктурированных данных недоступна стандартным программным инструментам и средствам, с которыми рядовые пользователи сталкиваются в повседневной жизни, поэтому также под BigData понимают комплекс подходов и технологий (в том числе MapReduce), призванных оптимизировать результаты функционирования больших данных в каждой проекции. В основе таких подходов лежит система распределенных вычислений, в которой большие данные параллельно обрабатываются на высокопроизводительных ЭВМ, объединенных в кластер.

О том, как Google начал «бороздить просторы голубого океана»

Выход на новый рынок для «поисковика» был необходимостью, чтобы сохранить конкурентное преимущество своего основного сервиса. Скорость выполнения запросов при вводе «куплю машину Москва» или «курсовая работа скачать» в поисковой строке – одно из основных конкурентных преимуществ (недостатков в случае Bing), которые обеспечивается технологиями обработки больших данных.

Big Data Technologies. Лекция 3. MapReduce

Не дифференцируя пул проблем, с которым столкнулись разработчики нового программного обеспечения, стоит сосредоточиться на 2х из них: «Как хранить данные для поисковых запросов и обращаться к ним через допустимый временной лаг?». Так на рынке была запущена технология MapReduce.

О том, как Google «поедает бифштексы»

Парадигма новой «гугловской» технологии обработки больших массивов данных строится на основном правиле управления временем «поедания слонов»: разрежь и съешь. Стоит представить большой информационных поток, выделить из него некоторый сегмент. Он более чем «большой» и не может быть обработан на стандартном ПК.

Далее дробим этот сегмент на «более мелкие кусочки» и приемлемые, для обработки на стандартном ПК. В книге Глеба Архангельского «Тайм-Драйв» этот процесс относится к решению сложных задач-слонов. Разделив на части-бифштексы, можно последовательно избавиться от большой задачи.

Google MapReduce также делит поток на бифштексы, съедает кусочек за кусочком, используя стандартные кластеры (ни чем не отличающиеся по мощности от ноутбука, на котором я пишу эту статью), далее собирает результаты обработки воедино и отправляет пользователю как результат на запрос. К сожалению, «велосипед не был изобретен» компанией Google, тем не менее, компания решила основную задачу, оптимизировав поисковую машину.

Как в сафари сделать Гугл на телефоне

Внедренная архитектура MapReduce смогла обеспечить:

  • автоматическую параллельную обработку данных из огромного массива по множеству узлов обработки (кластеров)
  • эффективную балансировку загрузки этих вычислительных узлов, не дающую им простаивать или быть перегруженными сверх меры (мастер-узел)
  • технологию отказоустойчивой работы (резервные серверы и фантомные мастера)

О том, как правильно резать и есть бифштексы

При проектировании MapReduce разработчики «гугла» преследовали цель размещения модулей, которые реализуют процедуры «map» и «reduce» на чанк-серверах – базовых элементах системы GFS.

Вышеупомянутая система GFS – распределенная кластерная файловая система гугл. Применимо к данной статье – это аппаратный «бэкграунд» для реализации MapReduce. Основные принципы системы заключаются в перекрестном хранении дублированной информации на кластерах с «повышенной» защитой от сбоев. По большому счету, вся защита осуществляется посредством «фантомов» и образов (у любого объекта есть пара, готовая заменить его в случае поломки).

Чанк-сервер или CSS – базовая единица хранилища информации для GFS.

Возвращаясь к поеданию бифштексов

Как и GFS, технология MapReduce построена по принципу «главный (мастер) — подчиненные (исполнители)». Мастер управляет/координирует множество исполнителей/работников, находящихся на разных чанк-серверах. Все исполнители делятся на два типа по исполняемым функциям: mappers или «мапперы», выполняющие функцию map, и «редьюсеры», отвечающие, соответственно, за функцию reduce.

Рис. 1 Верхний уровень матрешки устройства MapReduce

На вход технология MapReduce подается массив «на обработку», который предварительно разделяется на количество частей (N), соответствующее количеству мапперов. Размеры каждой от 16 до 64 мегабайт. Стоит оговориться, есть несколько версий и методологий работы данной технологии. От версии к версии некоторые численные значения (в частности по «весу» единицы обработки) могут меняться. Целью данной статьи служит показать общую концепцию работы технологии.

Получив адреса M частей массива, мастер MapReduce формирует частные задания для N функций мапперов и отправляет их в соответствующие мапперам чанки. Далее каждое задание обрабатывается функцией map (работа мапперов). Поскольку мапперы работают параллельно и независимо друг от друга, требуется в N раз меньше времени, чем при линейной обработке.

Финальная стадия работы мапперов – разделённый на части массив промежуточных данных, содержащих неупорядоченные списки пар «ключ – значение». Количество таких частей должно быть эквивалентно количеству редьюсеров, но в реальности массив пар, содержащих один и тот же ключ, значительно больше. Для сокращения размера до требуемого, MapReduce использует процедуру (combine) – процедуру предварительного сбора данных. Эта процедура присваивает популярным/часто встречаемым парам новое промежуточное значение. Идеальная функция для накопления данных о частоте использования «слова» внутри переменных, однако коммутативностью и ассоциативностью данных для обработки редьюсеров.

Рис. 2 Второй уровень матрешки устройства MapReduce — Линия

Агрегированный массив промежуточных данных отправляется к редьюсерам (логистика также осуществляется посредством мастера). На каждого «работника» желательно подать пары с одинаковым ключом (в силу алгоритма обработки). Вопрос: как это сделать, если пары разбросаны по разным частям списка, сформированного мапперами?

Тут MapReduce использует процедуру (partioning), перераспределяя и отправляя пакеты к «нужным» работникам, в соответствии с парами «ключ-значение». Процесс времяемкий и энергозатратный (требуется большое количество итераций на проверку), но скорость выполнения работниками сборки готовых к сборке входных данных компенсирует время на процедуру распределения.

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

Разработчики Google увидели потенциал системы и стали использовать ее не только для оптимизации поисковых запросов — Google Translate, Google Docs, Google Voice (что является вторичным рынком, частично покрывающим стартовые капиталовложения).

Концепт MapReduce был опубликован разработчиками, что дало возможность GNU создать планировщик распределения задач – симулятор MapReduce.

Private Companies, такие как Fb или Alibaba, последовали примеру Google и создали свои системы обработки больших объемов данных, тем самым объявив «гонку вооружения».

  1. Официальный сайт компании Cloudera http://www.cloudera.com/
  2. Агрегатор статей в области программирования http://docs.mongodb.org/
  3. Информационный портал «о новых технологиях» http://www.computerra.ru/
  4. Новостной агрегатор http://venturebeat.com/
  5. Официальный сайт компании IBMhttp://www.ibm.com/
  6. Портал для IT-специалистов http://habrahabr.ru/
  7. Аналитическое агентство http://www.tadviser.ru/
  8. Официальный сайт консалтинговой компании McKinsey http://www.mckinsey.com
Google photos объем емкости

Источник: scienceforum.ru

Что такое MapReduce

MapReduce – это модель распределённых вычислений от компании Google, используемая в технологиях Big Data для параллельных вычислений над очень большими (до нескольких петабайт) наборами данных в компьютерных кластерах, и фреймворк для вычисления распределенных задач на узлах (node) кластера.

НАЗНАЧЕНИЕ И ОБЛАСТИ ПРИМЕНЕНИЯ

MapReduce можно по праву назвать главной технологией Big Data, т.к. она изначально ориентирована на параллельные вычисления в распределенных кластерах. Суть MapReduce состоит в разделении информационного массива на части, параллельной обработки каждой части на отдельном узле и финального объединения всех результатов.

Программы, использующие MapReduce, автоматически распараллеливаются и исполняются на распределенных узлах кластера, при этом исполнительная система сама заботится о деталях реализации (разбиение входных данных на части, разделение задач по узлам кластера, обработка сбоев и сообщение между распределенными компьютерами). Благодаря этому программисты могут легко и эффективно использовать ресурсы распределённых Big Data систем.

Технология практически универсальна: она может использоваться для индексации веб-контента, подсчета слов в большом файле, счётчиков частоты обращений к заданному адресу, вычисления объём всех веб-страниц с каждого URL-адреса конкретного хост-узла, создания списка всех адресов с необходимыми данными и прочих задач обработки огромных массивов распределенной информации. Также к областям применения MapReduce относится распределённый поиск и сортировка данных, обращение графа веб-ссылок, обработка статистики логов сети, построение инвертированных индексов, кластеризация документов, машинное обучение и статистический машинный перевод. Также MapReduce адаптирована под многопроцессорные системы, добровольные вычислительные, динамические облачные и мобильные среды.

ИСТОРИЯ РАЗВИТИЯ ГЛАВНОЙ ТЕХНОЛОГИИ BIG DATA

Авторами этой вычислительной модели считаются сотрудники Google Джеффри Дин (Jeffrey Dean) и Санджай Гемават (Sanjay Ghemawat), взявшие за основу две процедуры функционального программирования: map, применяющая нужную функцию к каждому элементу списка, и reduce, объединяющая результаты работы map. В процессе вычисления множество входных пар ключ/значение преобразуется в множество выходных пар ключ/значение.

Изначально название MapReduce было запатентовано корпорацией Google, но по мере развития технологий Big Data стало общим понятием мира больших данных. Сегодня множество различных коммерческих, так и свободных продуктов, использующих эту модель распределенных вычислений: Apache Hadoop, Apache CouchDB, MongoDB, MySpace Qizmt и прочие Big Data фреймворки и библиотеки, написанные на разных языках программирования. Среди других наиболее известных реализаций MapReduce стоит отметить следующие:

  • Greenplum — коммерческая реализация с поддержкой языков Python, Perl, SQL и пр.;
  • GridGain — бесплатная реализация с открытым исходным кодом на языке Java;
  • Phoenix — реализация на языке С с использованием разделяемой памяти;
  • MapReduce реализована в графических процессорах NVIDIA с использованием CUDA;
  • Qt Concurrent — упрощённая версия фреймворка, реализованная на C++, для распределения задачи между несколькими ядрами одного компьютера;
  • CouchDB использует MapReduce для определения представлений поверх распределённых документов;
  • Skynet — реализация с открытым исходным кодом на языке Ruby;
  • Disco — реализация от компании Nokia, ядро которой написано на языке Erlang, а приложения можно разрабатывать на Python;
  • Hive framework — надстройка с открытым исходным кодом от Facebook, позволяющая комбинировать подход MapReduce и доступ к данным на SQL-подобном языке;
  • Qizmt — реализация с открытым исходным кодом от MySpace, написанная на C#;
  • DryadLINQ — реализация от Microsoft Research на основе PLINQ и Dryad.

MapReduce – это разделение, параллельная обработка и свертка распределенных результатов

КАК УСТРОЕН MAPREDUCE: ПРИНЦИП РАБОТЫ

Прежде всего, еще раз поясним смысл основополагающих функций вычислительной модели:

  • mapпринимает на вход список значений и некую функцию, которую затем применяет к каждому элементу списка и возвращает новый список;
  • reduce (свёртка) – преобразует список к единственному атомарному значению при помощи заданной функции, которой на каждой итерации передаются новый элемент списка и промежуточный результат.
Как восстановить старые закладки в Гугл Хром

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

Сама вычислительная модель состоит из 3-хшаговой комбинации вышеприведенных функций:

  1. Map – предварительная обработка входных данных в виде большого список значений. При этом главный узел кластера (master node) получает этот список, делит его на части и передает рабочим узлам (worker node). Далее каждый рабочий узел применяет функцию Map к локальным данным и записывает результат в формате «ключ-значение» во временное хранилище.
  2. Shuffle, когда рабочие узлы перераспределяют данные на основе ключей, ранее созданных функцией Map, таким образом, чтобы все данные одного ключа лежали на одном рабочем узле.
  3. Reduce – параллельная обработка каждым рабочим узлом каждой группы данных по порядку следования ключей и «склейка» результатов на master node. Главный узел получает промежуточные ответы от рабочих узлов и передаёт их на свободные узлы для выполнения следующего шага. Получившийся после прохождения всех необходимых шагов результат – это и есть решение исходной задачи.

Принцип работы MapReduce

Источник: biconsult.ru

Технология Google MapReduce: разделяй и властвуй

bannerbanner

Логистика — замечательная штука. Стоит заглянуть в хранилище какого-нибудь гипермаркета — и становится ясно: без тщательного упорядочивания товаров в нём и речи не может идти о какой-либо эффективной торговле. Между тем гигантские торговые дома преспокойно открывают свои двери десяткам тысяч потребителей и легко разыскивают в недрах своих бездонных складов требуемые товары.

С информацией дело обстоит примерно так же. Сохранить её — только одна из задач. Информация требует обработки. Каким бы эффективным ни было хранилище данных, оно не поможет её обработать.

В компании Google с этой проблемой знакомы не понаслышке. Её трудолюбивые боты круглосуточно собирают контент всё более разрастающегося интернета и передают его в кластер Google, где правит бал распределённая файловая система GFS. Она распределяет петабайты данных по сотням тысяч чанк-серверов не хуже матёрого специалиста по логистике, по ходу дела обеспечивая им надежное хранение, которому не вредят ни возможные сбои, ни отказы оборудования.

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

Как узнать, на каких веб-страницах есть эти ключевые слова? Какой ресурс содержит всего одно ключевое слово, а какой — сразу несколько? Тут без хорошей индексной базы не обойтись.

Сформировать такую базу на петабайтном массиве данных — задачка нетривиальная. Фактически требуется поочередно «пройтись» по каждому документу и определить, содержит ли он требуемое слово. Как ни крути, процесс линейный.

Но только не для компании, обладающей кластером из полумиллиона компьютеров.

С ним легко можно применять известную парадигму информатики «разделяй и властвуй», поделив информационный массив на части и отдав каждую из них индексировать отдельному серверу. Ну а после выполнения индексации по частям остается собрать найденное решение воедино.

Именно для такой работы Google и была разработана технология MapReduce — средство эффективного распараллеливания задач, в обычных условиях решаемых линейно.

Помните, в детстве на уроках родной речи нам давали задание на внимательность? Найти, например, на странице из «Золотой рыбки» все буквы «О» и подсчитать их количество. Школьники скрупулёзно, строка за строкой, высматривали «О», подчеркивали их, а потом суммировали подчёркнутое.

Теперь представьте, насколько быстрее пошло бы дело, если бы мы раздали по строке каждому ученику из класса, который, подсчитав количество букв, сообщил бы его заранее назначенному «главному по буквам». Если не вдаваться в подробности, технология MapReduce работает именно таким образом.

Конечно, разрабатывая MapReduce, сотрудники Google Джеффри Дин (Jeffrey Dean) и Санджай Гемават (Sanjay Ghemawat) вдохновлялись не школьными заданиями. Они имели другой замечательный источник энтузиазма. Ещё в конце пятидесятых годов прошлого столетия для обработки данных, представленных линейными списками, был разработан язык программирования Lisp — предок целого семейства языков, использующих парадигму функционального программирования.

Что такое Google в математике

Lisp и другие функциональные языки поддерживают интересную программную модель, именуемую Map/Reduce. Из её названия следует, что работают в ней две процедуры — map, применяющая нужную функцию к каждому элементу списка, и reduce, объединяющая результаты работы map.

Замечательным свойством модели Map/Reduce является всеядность. С её помощью, например, удобно организовать счётчик появления искомых слов в большом файле (построение Term-вектора) или счётчик частоты обращений к заданному адресу, вычислить объём всех веб-страниц со всех URL конкретного хост-узла или же создать список всех адресов, содержащих необходимые данные.

Чтобы выполнить индексацию сохраняемого в кластере Google веб-контента, разработчики MapReduce приспособили общую модель функциональных языков программирования к своим целям.

Они предположили, что вся обрабатываемая MapReduce информация может быть представлена в виде списка пар, каждая из которых состоит из ключа и значения. В массиве веб-контента ключом, конечно же, является искомое слово, а его значением — число 1, подтверждающее присутствие этого слова.

В самом простом варианте программной модели Google MapReduce процедура map получает на вход список слов, содержащихся в обрабатываемых документах. Она преобразует каждый элемент в пару, одним элементом которой является слово, а другим — число 1.

Затем за список берётся процедура reduce, которая группирует элементы списка с одинаковыми ключами (то есть словами) и суммирует единички. В результате на выходе оказывается список всех ключевых слов с количеством их упоминаний в тех или иных документах. А это и есть индексная база поисковой системы.

Как видите, ничего нового создатели MapReduce не изобрели. Их настоящая заслуга в другом. На самом деле MapReduce — это не только программная модель, используя которую можно решать задачи сортировки и группировки данных. Это — целая архитектура, обеспечивающая:

  • автоматическое распараллеливание данных из огромного массива по множеству узлов обработки, выполняющих процедуры Map/Reduce;
  • эффективную балансировку загрузки этих вычислительных узлов, не дающую им простаивать или быть перегруженными сверх меры;
  • технологию отказоустойчивой работы, предусматривающую тот факт, что при выполнении общего задания часть узлов обработки может выйти из строя или по какой-либо другой причине перестать обрабатывать данные.

Таким образом, Google MapReduce, с одной стороны, предоставляет пользователю процедуры обработки его данных, а с другой — делает для него прозрачным процесс распараллеливания этой обработки на могучем кластере Google.

Как же им это удалось?

Параллельные вычислители, GFS и всё тот же кластер

Наиболее светлой мыслью при проектировании MapReduce была идея разместить модули, реализующие процедуры map и reduce, на тех самых чанк-серверах — основе файловой системы GFS. Такой подход приближает хранящиеся в GPS модули к функциям их обработки. Экономия сетевого трафика налицо.

Дальше — больше. Как и GFS, технология MapReduce построена по принципу «главный — подчиненные». «Голова» MapReduce — процедура Master — управляет множеством разбросанных по чанк-серверам «работников» (workers), часть из которых отвечает за функцию map (их зовут mappers, или «мэпперы»), а остальные, соответственно, за reduce (reducers — «редьюсеры»).

На вход MapReduce поступает требующий обработки массив, «разрезанный» на M (по числу мэпперов) частей размером от 16 до 64 мегабайт (стоит напомнить, что именно такой размер имеет чанк в файловой системе GFS). Получив адреса M частей массива, Master MapReduce формирует частные задания для M функций мэпперов и раздает каждой из них адрес чанка, который надлежит подвергнуть процедуре map. Поскольку мэпперы работают параллельно и независимо друг от друга, требуется в M раз меньше времени, чем при линейной обработке.

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

Как настроить Google через прокси

Чтобы сократить его размер, MapReduce использует процедуру предварительного агрегирования данных, присваивая таким популярным парам новое промежуточное значение. Эта процедура именуется combine и по своей сути очень похожа на reduce. Необходимо заметить, что combine можно использовать лишь в тех случаях, когда функция, которую используют на стадии reduce для объединения данных, обладает свойствами коммутативности и ассоциативности.

Агрегированный до требуемого размера массив промежуточных данных может поступать на R «работников», выполняющих reduce. Стоит напомнить, что reduce в простейшем виде работает со всеми значениями одного ключа — например, с количеством упоминаний какого-либо слова. Это значит, что на каждого «работника» желательно подать пары с одинаковым ключом. Проблема заключается в том, что они разбросаны по разным частям списка, сформированного мэпперами. Как же быть?

Последним этапом перед выполнением процедуры reduce является процедура распределения (partitioning), в результате которой пары с одинаковым ключом попадают на одних и тех же «работников». Да, процесс требует времени и значительного сетевого трафика, но всё это компенсируется скоростью работы на следующем этапе.

Каждый редьюсер в конечном итоге создает файл, где хранятся отсортированный (например, по алфавиту) список ключей, за которые он отвечал, и результат обработки значений этих ключей (например, их сумма).

R «работников» создают R результирующих файлов, о чём и докладывают мастеру MapReduce. Получив подтверждение от всех «работников», он считает задание выполненным и передает адреса результирующих файлов клиентскому приложению.

Так в недрах кластера Google и рождается индексная база интернета, строятся графы популярности URL и выполняются прочие необходимые для работы поисковой системы операции.

И не только для неё. Разработчики приложений Google, в которых требуется обработка больших массивов данных, быстро оценили достоинства параллельного вычислителя MapReduce и написали свои варианты процедур map и reduce. Именно так пополняется словарная база переводчика Google Translate, так формирует данные об орфографии десятков языков спеллчекер Google Docs и индексирует голосовые морфемы Google Voice. Применений MapReduce было найдено множество.

Как и в случае с файловой системой GFS, Google пояснила только идеологию MapReduce, не раскрывая конкретных реализаций её алгоритмов. Однако и этого хватило, чтобы сообщество open source в рамках проекта Hadoop реализовало планировщик распределения задач по узлам вычислительного кластера Hadoop YARN и фреймворк Hadoop MapReduce, позволяющий создавать собственные мэпперы и редьюсеры.

Вскоре MapReduce начала обрабатывать «большие данные» в других поисковых системах, социальных сетях и интернет-магазинах.

Между тем с момента разработки этой технологии интернет серьёзно изменился. Как в плане контента, где наряду с текстовыми данными всё большую роль стали играть изображения, видео, звук, картографическая информация, так и в плане социальном. Нынешний интернет-житель в качестве стартовой страницы своего браузера всё реже ставит поисковую систему и всё чаще — социальную сеть. Контент нынешнего интернета более динамичный: он меняется буквально ежесекундно.

Технология же MapReduce, ориентированная на пакетную обработку данных (мастер раздал задания, подождал, собрал результаты) не могла эффективно учитывать эти постоянные изменения.

Именно поэтому в июле 2010 года Google представила свою новую систему распределенного индексирования интернет-контента Caffeine. В ней трудится обновленный вариант технологии MapReduce, ориентированный на инкрементное формирование распределённой индексной базы.

Теперь индекс Google обновляется не единовременно, но редко, а понемногу, но часто. И это позволяет проиндексировать такие мимолетные, казалось бы, ресурсы, как посты социальных сетей или многочисленные навигационные запросы к сервису Google Maps.

Используя свои лучшие наработки и тщательно исследуя тенденции нашей с вами работы в интернете, Google старается делать упреждающие шаги в развитии своего сердца — поисковой системы.

Источник: www.computerra.ru

Рейтинг
Загрузка ...