数据库 – 用于简单消息应用的Cassandra数据模型
我正在尝试学习Cassandra,总是找到最好的方法是开始创建一个非常简单和小的应用程序.因此,我正在创建一个使用Cassandra作为后端的基本消息传递应用程序.我想做以下事情:
>用户将创建一个用户名,电子邮件和密码的帐户.该 当我来自关系数据库的世界,我的关系数据库将如下所示: 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,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,[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]; 干杯 解决方法是的,当从关系数据库背景出发时,适应Cassandra的局限性总是很困难的.既然我们还没有在Cassandra加盟的奢侈品,那么你经常想要尽可能多地填入一张桌子.在你的情况下,这将是users_by_username表.Cassandra的一些功能应该允许你这样做. 由于您是Cassandra的新手,您可能会使用目前处于测试版本的Cassandra 3.0.在3.0中有一个很好的功能,称为物化视图.这将允许您将users_by_username作为基表,并将users_by_email创建为实例化视图.那么当你更新基表时,Cassandra会自动更新视图. 帮助您的另一个功能是用户定义的类型(在C * 2.1及更高版本中).不必为关注者和消息创建单独的表,您可以创建UDT的结构,然后在用户表中保留这些类型的列表. 因此,您的模式的简化视图可能是这样的(我没有显示一些字段,如时间戳来保持这个简单,但是这些容易添加). 首先创建你的UDT的: CREATE TYPE user_follows ( followed_username text,street text,); CREATE TYPE msg ( from_user text,body text ); 接下来我们创建你的基表: CREATE TABLE users_by_username ( username text PRIMARY KEY,password text,follows list<frozen<user_follows>>,followed_by list<frozen<user_follows>>,new_messages list<frozen<msg>>,old_messages list<frozen<msg>> ); 现在我们创建一个通过电子邮件分区的物化视图: CREATE MATERIALIZED VIEW users_by_email AS SELECT username,password,follows,new_messages,old_messages FROM users_by_username WHERE email IS NOT NULL AND password IS NOT NULL AND follows IS NOT NULL AND new_messages IS NOT NULL PRIMARY KEY (email,username); 现在让我们来看看它能做些什么.让我们创建一个用户: INSERT INTO users_by_username (username,email,password ) VALUES ( 'someuser','someemail@abc.com','somepassword'); 让用户跟随另一个用户: UPDATE users_by_username SET follows = [{followed_username: 'followme2',street: 'mystreet2'}] + follows WHERE username = 'someuser'; 我们来给用户一个消息: UPDATE users_by_username SET new_messages = [{from_user: 'auser',body: 'hi someuser!'}] + new_messages WHERE username = 'someuser'; 现在看看表中有什么? SELECT * FROM users_by_username ; username | email | followed_by | follows | new_messages | old_messages | password ----------+-------------------+-------------+---------------------------------------------------------+----------------------------------------------+--------------+-------------- someuser | someemail@abc.com | null | [{followed_username: 'followme2',street: 'mystreet2'}] | [{from_user: 'auser',body: 'hi someuser!'}] | null | somepassword 现在我们检查一下我们的物化视图是否正常工作: SELECT new_messages,old_messages FROM users_by_email WHERE email='someemail@abc.com'; new_messages | old_messages ----------------------------------------------+-------------- [{from_user: 'auser',body: 'hi someuser!'}] | null 现在让我们看一下电子邮件,并将其放在旧邮件中: BEGIN BATCH DELETE new_messages[0] FROM users_by_username WHERE username='someuser' UPDATE users_by_username SET old_messages = [{from_user: 'auser',body: 'hi someuser!'}] + old_messages where username = 'someuser' APPLY BATCH; SELECT new_messages,old_messages FROM users_by_email WHERE email='someemail@abc.com'; new_messages | old_messages --------------+---------------------------------------------- null | [{from_user: 'auser',body: 'hi someuser!'}] 所以希望能给你一些可以使用的想法.看看集合文档(即列表,地图和集合),因为这些文档真的可以帮助您在一个表格中保留更多的信息,并且像表格中的表格一样. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |