Twitter

как сделать свой Twitter?



как сделать  свой Twitter?

Мы будем использовать базу данных(БД) Redis.
  Html страницу вы сделаете сами используя Html 5.
А как использовать такую БД я раскажу

Шаг 0

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



Шаг 1

Аккаунты будем хранить в виде отдельных пар ключ-значение, где ключём будет логин пользователя, а значением – сериализированный массив (язык не имеет значения, например, РНР), в котором уже все о юзере, его имя, пол, дата регистрации и остальные данные. Вместо сериализации даже лучше использовать JSON – тогда мы вообще не будем зависеть от языка приложения, ведь JSON умеет обрабатывать любой современный язык программирования.
Команда SET admin “{name:’supervasya’,age:21,sex:’m’,registered:’27.07.2009’} ” – записывает нового юзера с логином admin. Теперь выполнив запрос GET admin мы получим JSON-строку с данными.
Для авторизации мы используем отдельное значение: SET admin_pass “md5(password)” – ключем здесь также логин, но с добавлением строки «_pass», а значение – md5 хеш пароля.
Авторизация будет в два шага (для надежности, но можно и в один). Сначала проверим, существует ли логин: EXISTS admin, если все ок (значит в базе есть такой юзер), извлекаем его хеш пароля для проверки: GET admin_pass. Саму проверку и сравнение хешей придется делать уже в приложении.
Не забудем счётчик всех юзеров (а то ведь SELECT COUNT() здесь нету): INCR count_user - увеличит счетчик юзеров на 1.
Если тебе захочется иметь весь список юзеров, придется раскошелиться на еще одну переменную, например, загнав все логины в набор (set): SADD all_user_list admin. Таким образом, в all_user_list у нас будет хранится список всех логинов, по которым можно извлечь профайл аккаунта.

Шаг 2

Теперь будем хранить все твои сообщения. Ключем в данном случае будет метка времени, потому что ключ должен быть уникальным, да и вряд ли ты будешь постить что-то чаще раза в секунду (нефиг спамить!). Можем просто создать ключ, используя логин и метку времени, например, admin_11232142135, и хранить его как отдельное значение вместе с сообщением: SET admin_11232142135 “{author:’admin’,text:’моя супер статья!’,time: 11232142135,title:’статья!’} ”
Но чтобы облегчить себе жизнь, мы сделаем еще список, где будут хранится данные о времени постов каждого автора. Вот так: RPUSH admin_msgs 11232142135. Команда добавит в конец списка admin_msgs новое значение – метку времени твоего поста. Зачем? Для облегчения потом получения всех постов за определенное время или просто указанного количества, например, для постраничного вывода. Внутри списка даты уже отсортированные по времени, поэтому дополнительной сортировки ненужно.

Шаг 3

Если ты хочешь зафолловить (читать) Васю, необходимо сохранить логин Васи в твоем списке фоловверов. Для этого также применим списки, создав для каждого юзера список фолловеров: RPUSH admin_follow vasja. В списке admin_follow теперь будут хранится логины всех юзеров, которых хочет читать admin. Аналогично, если Вася хочет читать, что же про него пишет админ: RPUSH vasja _follow admin

Шаг 4

Выводим полную ленту сообщений. Выше мы уже умеем хранить все сообщения одного пользователя и хранить список тех, за кем он следит. Теперь выводим ленту сообщений, в которой будут как собственные сообщения юзера, так и все сообщения тех, за кем он следит. При этом, все сообщения должны идти в хронологическом порядке. Допустим, мы будем показывать только сообщения за последний час.
Здесь уже немного сложнее. Сначала выберем список всех пользователей, которых надо показать. Для этого сначала получим количество наших фолловеров (длину списка): LLEN admin_follow. Допустим, мы получили 2 (админ отслеживает двух юзеров): LRANGE admin_follow 0 1 – получаем в виде массива логины юзеров. Не забываем, что надо прибавить сюда и свой логин, так как наши сообщения также должны быть видны. Это уже придется делать самому приложению.
Далее, имея список логинов, нам надо выбрать все списки сообщений каждого юзера. К сожалению, для этого надо N раз вызвать команду LRANGE, указав ей каждый раз другой список (комбинацию логин игрока + _msgs). Конечно, в этом нет особо страшного ничего, ведь скорость работы Redis-а очень высокая, но этот момент может нуждаться в оптимизации. Например, есть команда KEYS которая ищет по паттерну все ключи и возвращает сразу список. Поэтому можно попробовать задать ей такое выражение, чтобы сразу получить все ключи сообщений (ведь они формируются через логин и метку времени, значит можно отфильтровать). Но это уже тебе как домашнее задание (на самом деле эта задача имеет несколько решений и не факт, что каждое из них самое лучшее).
Мы пока сделаем по-старинке, получив список сообщений для каждого юзера, программно сформируем из него список заранее подготовленных ключей для извлечения сообщений. Так как все сообщения идут по времени, достаточно полученный массив преобразовать из JSON-а в родной для твоего языка программирования и отбросить все значения, меньшие за текущее время минус 3600 (мы ведь за последний час выбираем). Если брать не за час, а просто последние 100, то задача еще более упростится.
Далее простым циклом формируем ассоциативный массив из комбинации логин + метка времени, где ключом будет метка времени (число, для обеспечения правильной сортировки), а значение – строка вида login_time (то есть так, как хранится у нас в Redis-e), а потом просто объединяем эти массивы. Язык сам позаботится о правильной последовательности, например, РНР так и сделает, используя команду array_merge и, если надо array_sort.
Эту часть нам пришлось вынести из базы и обработать в приложении, хотя при обычной архитектуре эта нагрузка легла бы на SQL-движок. Но это расплата за масштабируемость, поэтому не стоит переживать за нагрузку на сервере.
Последний штрих – сформируем команду к Redis-у на извлечение всех сообщений, ключи которых мы уже подготовили. У сервера есть волшебная команда, которой так не хватает другим популярным системам вроде memcached (там пытаются приспособить для этого теги) – MGET список_ключей, то есть одной командой получаем все ключи, имена которых передали. Остается только превратить наш массив в строку, разделителем служит символ пробела и все, мы сразу получим массив JSON-строк с сообщениями. Его даже сразу можно передать на веб-страницу, ведь с JSON умеет работать любой AJAX-фреймворк. На счет производительности не стоит переживать – операция декодирования JSON в родной для языка массив везде очень и очень быстрая, даже если речь идет о сотнях или тысячах преобразованиях.
Аналогично можно отобразить список всех фолловеров – ведь мы храним их в списке admin_follow, в котором хранятся логины, а значит, используя потом MGET команду, мы сразу достанем профайлы всех юзеров, за которыми следит админ.
Я ничего не сказал об удалении данных – ведь вдруг Вася окажется занудным типом или спаммером и ты захочешь отписаться от него. Для этого надо просто удалить из списка admin_follow его логин, что делает команда LREM, которой стоит передать только логин и все, нет больше Васи.

Что в результате?

Сейчас реляционные базы данных (SQL СУБД) уже не правят миром, особенно если речь идет о высоконагруженных проектах или сайтах, где надо обслуживать клиентов без задержки. Если раньше все проблемы пытались решить кешированием, то сегодня мы видим, как гиганты индустрии просто уперлись в ограничения баз данных и в поисках выхода попробовали посмотреть на традиционные кеши с другой стороны. И получилось! Добавив чуточку смекалки и пару новых команд теперь можно делать почти все, что раньше требовало сложных SQL-запросов, используя всего пять-шесть команд. При этом не важно, один сервер, десять или тысяча, мы вообще никак не ограничены в масштабировании! Конечно, не стоит сразу бросать любимый мускул и переписывать под Redis или MemcachedDB, но если ты делаешь сайт, где надо что-то делать быстро, очень быстро, как можно быстрее (ну типа чата, твиттера или онлайн игры, а то и биржевой системы) – попробуй посмотреть на мир key-value баз данных!
Может это то, что надо! А SQL-базам оставим нудные дела вроде построения аналитики и анализа данных.