---
title: "Архитектура и история i-News.kz"
description: "Всем привет! Я долго собирался с мыслями и в итоге решился описать архитектуру своего сайта - i-news..."
author: "iborodikhin"
published: "2011-07-27T00:37:57+00:00"
modified: "2011-07-27T00:37:57+00:00"
locale: "ru"
canonical_url: "https://yvision.kz/post/arhitektura-i-istoriya-i-news-kz-144445"
markdown_url: "https://yvision.kz/post/arhitektura-i-istoriya-i-news-kz-144445/markdown"
site_name: "Yvision.kz"
---

# Архитектура и история i-News.kz

> Всем привет! Я долго собирался с мыслями и в итоге решился описать архитектуру своего сайта - i-news...

Всем привет! Я долго собирался с мыслями и в итоге решился описать архитектуру своего сайта - [i-news.kz](http://i-news.kz). Но для начала **немного истории**.

В далёком 2008 году я, вместе с товарищем Сашей Малым (Prankster) делал многообещающий (и ныне покойный) проект - uno.kz и в его рамках нам очень хотелось запустить новостной сайт. Останавливал нас тот факт, что новости эти кто-то должен размещать на сайте. Т.е. нужен человек, который будет заниматься скучной монотонной работой (примерно так, как сделано на www.zakon.kz).

Внезапно в одной из бесед мой хороший друг Никита Вершинин (endeveit) упомянул, что собирается делать свой [агрегатор новостей](http://thenews.kz). Тогда я понял, что скучную монотонную работу можно здорово переложить на плечи программы. Так появился новостной раздел на uno.kz.

Прошло время и наши с Сашей пути разошлись не самым добрым образом, а чуть позже uno.kz умер. Я взял тот движок и развернул под именем [i-news.kz](http://i-news.kz) на дешёвом shared-хостинге, где [i-news.kz](http://i-news.kz) проживал до декабря 2010 года. За это время в базе скопилось более 300 тыс. новостей.

Изначально все новости целиком хранились в базе MySQL и для поиска использовался полнотекстовый индекс. Пока новостей и посетителей было мало всё было супер. Потом в один из выходных мой аккаунт отключили за большую нагрузку на процессор.

Здесь появилась первая оптимизация - тексты новостей я перелил в файлы, а для поиска стал использовать [xml.yandex.ru](http://xml.yandex.ru). Из базы были удалены тексты и полнотекстовый индекс, таблица с новостями похудела с 2Гб до 800Мб, сайт задышал свободнее. Плюс кеши и прочие мелочи - можно жить.

Однако через примерно полгода хостер опять взбунтовался, заявив, что мой сайт тормозит весь сервер - ведь "в линуксе начинает тормозить файловая система, когда количество файлов в одном каталоге превышает 50 тыс., а у вас их 300 тыс.". И плевать, что файлы разложены по директориям - "мы сказали много, значит много". В этот момент тексты переехали из файлов в SQLite-базы, разбитые по файлам понедельно и по годам. Хранилище новостей и по сей день организовано в виде структуры DataStorage/2011/12.db - данные за 12-ю неделю 2011 года. К слову, это решение также подсказал Никита (правда, предложив за имя файла брать первые/последние 2 символа из md5($news_id)). За что ему низкий поклон.

В конце-концов, в ноябре 2010 года хостер безапелляционно попросил меня уйти, сославшись на высокие нагрузки. Всё, что мне оставалось - арендовать выделенный реальный сервер и разместиться там. Пока суть да дело проект несколько недель жил на моём компьютере, постоянно включенном и подключенном через 512кб/с канал Алма-ТВ. Потом он переехал на довольно слабую машинку с двухъядерным Athlon'ом и 2 Гб памяти.

Поскольку на своём сервере я сам себе хозяин, я смог использовать PHP 5.3 (на хостинге была версия 5.2), заменить MySQL на Percona Server, для поиска использовать Sphinx. Неизменным осталось лишь хранилище - это SQLite, разбитый по неделям.

Я долго искал, как же мне хранить [шинглы для определения нечётких дубликатов](http://download.yandex.ru/company/download/paper_65_v1.pdf), пока в один день меня не осенило, что шинглы ВСЕХ новостей мне совсем не нужны. Достаточно хранить их за определённый период, скажем, за две недели.

Последней оптимизацией, резко повысившей скорость работы сайта в целом и практически каждой страницы в отдельности стал практически полный уход от MySQL (Percona Server) в пользу моего хранилища на SQLite и Sphinx'а. Теперь все [служебные] данные новостей лежат в SQLite и поэтому мне не нужно вытаскивать их из MySQL'я, а вместо индексов используются атрибуты Sphinx'а. Т.е. чтобы выбрать первые 30 новостей в определённой категории я раньше делал как-то так:

- $news = $db->findAll([array](http://www.php.net/array)("cat_id" => 1));
- $news = $dataStorage->load_multi($news);

а теперь делаю как-то так:

- $sphinxClient->setFilter("cat_id", 1);
- $result = $sphinxClient->query("", "*");
- $news = $dataStorage->load_from_sphinx_result($result);

Для главной страницы такой подход позволил избавиться от N запросов в базу (где N - количество источников новостей, поскольку на главной отображается последняя новость каждого источника) и сделать всё одной сфинксовой группировкой с обратной сотрировкой по времени создания.

Таким образом, ныне зоопарк используемых технологий выглядит следующим образом:
- **MySQL** (Percona Server) для хранения информации про источники новостей, для ведения auto_increment и хранения дат новостей (для нахождения новости в DataStorage нужны id и дата, поскольку новости разбиты по неделям), для хранения очереди отправки почты и очереди публикации новостей (это была вынужденная мера, поскольку писать в SQLite можно только в один поток), для хранения комментариев - **PHP 5.3**, никакие специфичные фичи не используются, не 5.2 исключительно из-за нового сборщика мусора и умения лучше разруливать цикличные ссылки - **SQLite** для хранения основного - текстов новостей, id их категорий, id фидов и всей прочей информации - **Sphinx** для поиска, сортировки, группировки и т.д.

- **MongoDB** для хранения количества просмотров новостей и их рейтингов - **memcached** для кеширования редко изменяющихся данных (на длинное время до 10 мину) - **xcache** для оптимизации и кеширования кода, а также для кеширования оперативных данных (на короткое время до 1 минуты) - **lighttpd** в качестве веб-сервера (никаких апачей я на своём сервере не терплю) - **Ubuntu Server** в качестве ОС

Стоит отметить, что на этом же сервере располагается мой проект [internets.kz](http://internets.kz), в состав которого входит счётчик посещений, генерирующий в сутки порядка 100К хитов (отдельно от самого сайта [internets.kz](http://internets.kz) и сайта [i-news.kz](http://i-news.kz)). Загрузка сервера по графикам Munin не превышает 3.5%

В плане кода [i-news.kz](http://i-news.kz) содержит под капотом самопальный каркас (фреймворком это назвать нельзя) для разделения кода и представления. Для отправки почты используется Zend_Mail, а для кеширования Zend_Cache. Для общения с MySQL используется PDO, для разбора HTML - DomDocument+DomXPath.

В целом, я очень благодарен всем, кто [не всегда] по своей воле помогал мне с проектом. Я очень многому научился и, уверен, ещё научусь.

Если у кого-то остались вопросы - буду рад ответить в комментариях.

---

Source: [https://yvision.kz/post/arhitektura-i-istoriya-i-news-kz-144445](https://yvision.kz/post/arhitektura-i-istoriya-i-news-kz-144445)