Показать сообщение отдельно
Старый 17.10.2015, 11:32   #1
St_AnGer
Элита
 
Аватар для St_AnGer
 
Регистрация: 21.01.2010
Адрес: Россия, Рязанская область, г.Михайлов
Сообщений: 2,067
Написано 1,185 полезных сообщений
(для 2,828 пользователей)
Чат: PHP + MySQLi или что то другое?

Добрый день, Булка!

В целях развития решился я тут снова приняться за чатик аля Аська или (если брать из известного среди ньюфагов) Viber. Ну как чатик - полноценную систему обмена сообщениями с сохранением всего и вся чем обмениваются пользователи. Этот же чат будет и для яОСи (где то на Булке я уже выкладывал скрин меню по яОСь), и, в последующем, наверно, под Ведроид. Но не суть. Все наработки которые у меня были под яОСь были мной отвергнуты ввиду своей убогости и неоправданной сложности. В общем, начинаю с нуля.

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

На данный момент пишу веб-клиент (так как его куда проще реализовать, чем приложение под мобилки) и общий сервер на всё. Что есть в планах на реализацию:
- регистрация
- авторизация
- активация пользователя пятью голосами других пользователей или одним голосом администратора (изначально планировалось как корпоративный чат, посему лишних болтунов в нём не надо)
- просмотр списка неактивированных пользователей
- поиск пользователей
- добавление пользователей в список
- удаление пользователей из списка
- добавление групп пользователей (привет, Аська!)
- изменение групп пользователей (пока что только изменение названия группы)
- перенос пользователей из контактного списка в созданные группы
- удаление групп (вместе со всеми пользователями что в ней состоят)
- создание бесед
- запрос списка бесед в которых состоит пользователь
- отсылка сообщений в беседы
- запрос списка сообщений в беседе

Сейчас имею реализованные с лёгкостью и полностью оттестированные первые 11 пунктов, уткнулся на создании бесед.
Беседы будут создаваться двумя путями:
1) беседа из отдельных выбранных пользователем участников;
2) беседа с выбранной группой пользователей.
С этим проблем нет, приведение к общему списку пользователей на серверной стороне я реализовал. Но, беседы ведь не должны дублироваться, вот тут у меня и начались сложности. Нужно перед созданием новой беседы произвести поиск уже существующей, по сформированному массиву пользователей и, исходя из результатов, или вернуть id старой беседы, или создать новую.


Вот конкретно что не знаю и не очень понимаю.

Пункт 1.
Каким образом организовать структуру таблиц базы данных для этого?
Есть 2 мысли:
а) таблица "chats" в которой есть поле owner (собственно тот кто создал) и поле users (в ней хранится сортированный json-массив id пользователей состоящих в диалоге)
б) таблица "chats" (есть аналогичное поле owner) и таблица "chat_users" (содержит записи о пользователях в конкретных беседах)

Чем нравится вариант "а":
- нет лишней таблицы
- данные о беседе и список её пользователей хранятся в одной записи, простой поиск по id беседы
- довольно простой поиск беседы зная только список пользователей из ней (сформировали json-массив и спокойно ищем по полю "users")
Чем не нравится вариант "а":
- "сложность" извлечения списка пользователей. Сложность в том, что сначала надо декодировать массив пользователей и только потом делать запрос к базе данных что бы узнать их имена и данные для отображения
- вытекающая из предыдущего проблема поиска списка бесед в которых состоит текущий пользователь

Чем нравится вариант "б":
- простота поиска бесед в которых состоит текущий пользователь
- простота извлечения (одним запросом) данных пользователей зная id беседы (SELECT по id беседы и пара JOIN-ов для данных пользователей)
Чем не нравится вариант "б":
- очень сложный и долгий поиск беседы зная только список пользователей из неё

Извлечение данных пользователей беседы так же важно, как и поиск самой беседы по списку пользователей (как писал выше - такой поиск необходим при создании беседы).


Пункт 2.
Как организовать саму переписку в беседе? Допустим, как добавить сообщение в базу данных понятно - INSERT и всё. Но как реализовать правильную выборку сообщений для пользователей состоящих в беседе? Если в беседе 1 пользователь - всё просто, один запрос. А если 10 пользователей - то это уже 10 запросов за одними и теми же данными. Вопрос скорости работы при 30-40 пользователях встанет ребром, а при 100 и более - сервер умрёт. Расширение мощности сервера не вариант - чаты существуют очень давно и изначально они были реализованы на машинах с мощностью меньшей, чем нынешние калькуляторы. Однако работало всё на ура.

В наличии VPS, его конфигурация такова: 2 ГГц проц, 1 ГБ оперативы, 10 гигов пространства на HDD, Debian в качестве ОСи, никаких "иксов", только консоль. Серверную сторону пишу на PHP + MySQLi (возможно заменю на Firebird SQL, очень уж я к нему прикипел на предыдущей работе).

Буду очень рад советам по этому направлению, потому что знаний по нему у меня чуть больше чем ноль. Читал статьи на хабре, много думал, рисовал разных схем, искал структуру и принцип работы Аськи, ВКонтакта, Фейсбука.

Сегодня узнал про некий Redis (нереляционная БД в ОЗУ), но как его готовить и с чем его употреблять - пока что представления не имею, хотя её данные мне очень понравились, особенно скорость работы (естественно она в десятки раз быстрее, чем любая хранимая на HDD база данных). Интересно было бы узнать мнение работавших/работающих с ним. И ещё было бы интересно узнать как из Redis в MySQLi данные перекочевряжить (лично мне удобнее читать из базы данных данные, чем из файлов "снимков" данных из ОЗУ), хотя скрипт переноса на том же PHP я скорее всего тоже накатаю довольно быстро.
__________________
Main PC:
Intel Core i5 4260U 1.44 GHz + LPDDR3 1x4096 1600 MHz + Intel HD Graphics 5000.

Asus Ёжик T101-MT:
Intel Atom N-570 1.66 Ghz + DDR2 2x1024 800 Mhz + Intel GMA 3150 128 Mb DDR2


Скачать Doom 2D: Remake v0.3.8a
(Offline)
 
Ответить с цитированием