Я пытаюсь изучить Cassandra и всегда найти лучший способ - начать с создания очень простого и небольшого приложения. Поэтому я создаю основное приложение для обмена сообщениями, которое будет использовать Cassandra в качестве исходного. Я хотел бы сделать следующее:
- Пользователь создаст учетную запись с именем пользователя, электронной почтой и паролем. электронная почта и пароль могут быть изменены в любое время.
- Пользователь может добавить другого пользователя в качестве своего контакта. Пользователь добавил бы свяжитесь со своим именем пользователя или электронной почтой. Контакты не нужны быть взаимным смыслом, если я добавлю пользователя, это мой контакт, я не нужно дождаться, когда они примут/одобрят что угодно, как в Facebook.
- Сообщение отправляется от одного пользователя другому пользователю. Отправитель должен иметь возможность видеть сообщения, которые они отправили (упорядоченные по времени), и сообщения, которые были отправлены им (упорядочены по времени). Когда пользователь открывает приложение, которое нужно проверить в базе данных для любых новых сообщений для этого пользователь. Мне также нужно отметить, прочитано ли сообщение.
Как я пришел из мира реляционных баз данных, моя реляционная база данных будет выглядеть примерно так:
UsersTable
username (text)
email (text)
password (text)
time_created (timestamp)
last_loggedIn (timestamp)
------------------------------------------------
ContactsTable
user_i_added (text)
user_added_me (text)
------------------------------------------------
MessagesTable
from_user (text)
to_user (text)
msg_body (text)
metadata (text)
has_been_read (boolean)
message_sent_time (timestamp)
Прочитав несколько учебников Cassandra, я подумал о том, как моделировать базу данных. Моя главная задача - очень эффективно моделировать базу данных. Поэтому я стараюсь избегать таких вещей, как вторичные индексы и т.д. Это моя модель:
CREATE TABLE users_by_username (
username text PRIMARY KEY,
email text,
password text
timeCreated timestamp
last_loggedin timestamp
)
CREATE TABLE users_by_email (
email text PRIMARY KEY,
username text,
password text
timeCreated timestamp
last_loggedin timestamp
)
Чтобы распределять данные равномерно и читать минимальное количество разделов (надеюсь, только один), я могу быстро найти пользователя на основе их имени пользователя или электронной почты. Недостатком этого является то, что я удваиваю свои данные, но стоимость хранения довольно дешевая, поэтому я считаю, что это хороший компромисс вместо использования вторичных индексов. Последний вход должен также быть написан дважды, но Cassandra эффективен при написании, поэтому я считаю, что это хороший компромисс.
Для контактов я не могу думать о каком-либо другом способе моделирования этого, поэтому я смоделировал его очень похоже на то, как я буду в реляционной базе данных. Это довольно денормализованный дизайн, который я считаю, который должен быть хорош для производительности в соответствии с книгами, которые я прочитал?
CREATE TABLE "user_follows" (
follower_username text,
followed_username text,
timeCreated timestamp,
PRIMARY KEY ("follower_username", "followed_username")
);
CREATE TABLE "user_followedBy" (
followed_username text,
follower_username text,
timeCreated timestamp,
PRIMARY KEY ("followed_username", "follower_username")
);
Я зациклился на том, как создать следующую часть. Для обмена сообщениями я думал об этой таблице, так как она создавала широкие строки, что позволяет упорядочивать сообщения. Мне нужно обмен сообщениями, чтобы ответить на два вопроса. Сначала нужно уметь показывать пользователю все сообщения, которые у них есть, а также показывать пользователю сообщения, которые являются новыми и не прочитаны. Это базовая модель, но я не уверен, как сделать ее более эффективной?
CREATE TABLE messages (
message_id uuid,
from_user text,
to_user text,
body text,
hasRead boolean,
timeCreated timeuuid,
PRIMARY KEY ((to_user), timeCreated )
) WITH CLUSTERING ORDER BY (timeCreated ASC);
Я также рассматривал использование таких вещей, как столбцы STATIC, для "склеивания" вместе пользователя и сообщений, а также SETS для хранения контактных отношений, но из моего узкого понимания до сих пор способ, которым я представлял, более эффективен. Я спрашиваю, есть ли какие-либо идеи для повышения эффективности этой модели, если есть лучшие практики, которые я делаю, или если есть какие-то скрытые проблемы, с которыми я могу столкнуться в этом проекте?
В заключение я пытаюсь моделировать запросы. Если бы я использовал базы данных отношений, это были бы, по сути, запросы, на которые я хочу ответить:
To Login:
SELECT * FROM USERS WHERE (USERNAME = [MY_USERNAME] OR EMAIL = [MY_EMAIL]) AND PASSWORD = [MY_PASSWORD];
------------------------------------------------------------------------------------------------------------------------
Update user info:
UPDATE USERS (password) SET password = [NEW_PASSWORD] where username = [MY_USERNAME];
UPDATE USERS (email) SET password = [NEW_PASSWORD ] where username = [MY_USERNAME];
------------------------------------------------------------------------------------------------------------------------
To Add contact (If by username):
INSERT INTO followings(following,follower) VALUES([USERNAME_I_WANT_TO_FOLLOW],[MY_USERNAME]);
------------------------------------------------------------------------------------------------------------------------
To Add contact (If by email):
SELECT username FROM users where email = [CONTACTS_EMAIL];
Then application layer sends over another query with the username:
INSERT INTO followings(following,follower) VALUES([USERNAME_I_WANT_TO_FOLLOW],[MY_USERNAME]);
------------------------------------------------------------------------------------------------------------------------
To View contacts:
SELECT following FROM USERS WHERE follower = [MY_USERNAME];
------------------------------------------------------------------------------------------------------------------------
To Send Message:,
INSERT INTO MESSAGES (MSG_ID, FROM, TO, MSG, IS_MSG_NEW) VALUES (uuid, [FROM_USERNAME], [TO_USERNAME], 'MY MSG', true);
------------------------------------------------------------------------------------------------------------------------
To View All Messages (Some pagination type of technique where shows me the 10 recent messages, yet shows which ones are unread):
SELECT * FROM MESSAGES WHERE TO = [MY_USERNAME] LIMIT 10;
------------------------------------------------------------------------------------------------------------------------
Once Message is read:
UPDATE MESSAGES SET IS_MSG_NEW = false WHERE TO = [MY_USERNAME] AND MSG_ID = [MSG_ID];
Приветствия