《Redis与MySQL在即时通讯聊天室中的应用与设计》

《Redis与MySQL在即时通讯聊天室中的应用与设计》 目录内容简介:详细内容:1数据库的引入2: MySQL基础及在聊天室中的应用2.1 MySQL基础1 建库,建表,增删查改2 数据表的约束3 数据表数据的插入,更新,删除4 数据表查询1 select基础查询2 WHERE条件查询3 ORDER BY排序4 LIMIT2.2 聊天室中数据表的设计3: Redis基础及在聊天室中的应用1 Redis基本概念2 聊天室中Redis常用数据结构:1 String2 Hash3 List4 Set4: C程序和数据库之间的通信5: 总结内容简介:1. 聊天室为什么需要数据库2. MySQL基础和聊天室中的使用3. Redis基础和聊天室中的使用4. C程序和数据库之间的通信5. 总结详细内容:1数据库的引入能不能不用任何数据库把用户信息、在线状态存在服务器内存里,就像:打开手机备忘录只打字不保存一旦闪退、关机所有内容全部消失.即:断电即清空、重启数据全丢如果聊天室不用数据库会出现:服务器一旦重启所有注册的用户账号、好友关系、聊天记录全部清零用户每次打开软件都要重新注册无法正常使用。因此,需要数据库.进一步的,我们会发现聊天室的数据有完全不同的特点可分成两类第一类需要永久保存、很少变动的数据。比如账号密码、个人资料、好友关系、群组信息、历史聊天记录。这些数据哪怕服务器重启、电脑关机也必须完好保留。第二类实时变动、不用永久保存、访问极频繁的数据。比如用户在线状态、临时验证码、用户离线消息。有人上线、下线在线状态一秒变动好几次用户登录后验证码就失效这些数据不需要长期存但是需要秒级快速查询。这就引出单一数据库虽然可以实现所有功能但是不同数据对存储性能和访问速度的要求不同因此聊天室通常采用MySQL和Redis结合的方案。永久稳定的数据交给MySQL高速实时的数据交给Redis两者搭配,撑起一个完整、流畅的聊天室系统。我给大家整理了一张场景对照表方便大家直观理解数据类型数据特点适配数据库用户账号、密码、资料长期保存、稳定不变MySQL好友、群组关系、历史消息结构化、需留存、关系复杂MySQL用户在线状态高频变动、实时查询Redis离线消息、临时验证码短期有效、快速读写Redis2: MySQL基础及在聊天室中的应用在聊天室中,我们要学,如何设计表、如何存取数据、如何保证数据关系合理安装教程:MYSQL安装教程2.1 MySQL基础1 建库,建表,增删查改mysql -u root -p (登录)show databases;create databaseStu;默认的编码方式 latin1 (单字节编码)(建库)-create databaseStucharacter set utf8;设置成 utf-8中文能正常显示/alterdatabase Stucharsetutf8;修改use Stu;select database();show tables;create table 信息( (建表)姓名 varchar(20),年龄 int);show create table 信息;alter table 信息 add(/drop/modify) 性别 char(10);2 数据表的约束引入:为防止 重复用户名、用户没有密码、好友表里出现一个不存在的用户 ID、年龄填负数这类错误数据 被插入到数据表MySQL中定义了一些维护数据库完整性的规则这些规则常称为表的约束。聊天室常用约束如下约束条件说明PRIMARY KEY主键约束用于唯一标识对应的记录FOREIGN KEY外键约束NOT NULL非空约束UNIQUE唯一性约束在聊天室的应用:比如,用户表CREATE TABLE user(id INTPRIMARY KEYAUTO_INCREMENT,username VARCHAR(50)UNIQUENOT NULL,password VARCHAR(100)NOT NULL);PRIMARY KEY:保证id不会重复UNIQUE:保证同一个人不可以重复注册3 数据表数据的插入,更新,删除以聊天室user表为例:1准备一张表CREATE TABLE user( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(100) NOT NULL, nickname VARCHAR(50), create_time DATETIME );字段作用聊天室用途id用户唯一编号好友关系、消息记录中引用username账号名登录、注册password密码登录验证nickname昵称显示给好友create_time注册时间记录用户信息2插入数据INSERT INTO user(username,password,nickname,create_time) VALUES( jack, 123456, Jack, NOW() );执行后:idusernamepasswordnicknamecreate_time1jack123456Jack2026-07-21 20:00:00注意这里没有插入id。因为id INT PRIMARY KEY AUTO_INCREMENT表示id由MySQL自动生成3更新数据UPDATE user SET password888888 WHERE usernamejack; //jack修改密码修改密码123456-888888执行后:idusernamepassword1jack8888884删除数据DELETE FROM user WHERE usernamejack; //注销账号执行前idusernamepasswordnickname1jack123456Jack2tomabcdefTom执行后idusernamepasswordnickname2tomabcdefTom但是,在实际聊天室中用户注销通常采用逻辑删除即修改状态字段从1到0而不是直接删除数据避免影响好友关系和历史消息补充:TRUNCATE和DETELE的区别TRUNCATE和DETELE都能实现删除表中的所有数据的功能但两者也是有区别的1、DELETE语句后可跟WHERE子句可通过指定WHERE子句中的条件表达式只删除满足条件的部分记录但是TRUNCATE语句只能用于删除表中的所有记录。2、使用TRUNCATE语句删除表中的数据后再次向表中添加记录时自动增加字段的默认初始值重新由1开始使用DELETE语句删除表中所有记录后再次向表中添加记录时自动增加字段的值为删除时该字段的最大值加13、DELETE语句是DML语句TRUNCATE语句通常被认为是DDL语句4 数据表查询目标:服务器收到客户端请求后通过SQL查询数据库找到需要的数据然后返回给客户端1 select基础查询1 *查询所有字段SELECT *FROM 表名;2 查询指定字段SELECT 字段1,字段2FROM 表名;-eg:SELECT username,passwordFROM user;2 WHERE条件查询SELECT 字段FROM 表WHERE 条件;-用户Jack登录时客户端:usernamejack服务器查询:SELECT passwordFROM userWHEREusernamejack;数据库返回123456服务器比较密码还可以查询好友(WHERE user_id1)和聊天记录(WHERE sender1ANDreceiver2)聊天室常用多条件查询,例如查询好友SELECT * FROM friend WHERE user_id1 AND friend_id2;聊天室中的查询大部分都是带条件查询而不是简单查询全部数据。3 ORDER BY排序可用于查询历史消息查询SELECT *FROM messageORDER BYtime;结果10:0110:0210:034 LIMITSELECT *FROM messageORDER BYtime DESC(DESC最新消息放最上面,ASC最早消息放最上面)LIMIT20;假设聊天记录100万条,用户打开聊天窗口,不可能一次加载100万条.只取最近20条消息2.2 聊天室中数据表的设计目的:以用户表,好友关系表,消息表,群成员表为例,熟悉MYSQL在聊天室中的用法和约束约束条件说明PRIMARY KEY主键约束用于唯一标识对应的记录FOREIGN KEY外键约束NOT NULL非空约束UNIQUE唯一性约束故可设计为:1. 用户表 user作用:保存用户基本信息用于注册登录查询用户资料表结构:字段类型约束说明idINTPRIMARY KEY用户唯一编号usernameVARCHAR(50)UNIQUE、NOT NULL用户名passwordVARCHAR(100)NOT NULL密码nicknameVARCHAR(50)昵称create_timeDATETIME注册时间CREATE TABLE user( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(100) NOT NULL, nickname VARCHAR(50), create_time DATETIME );2. 好友关系表 friend作用:保存用户之间的好友关系表结构:字段类型说明idINT关系编号user_idINT用户idfriend_idINT好友idcreate_timeDATETIME建立好友时间CREATE TABLE friend( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, friend_id INT NOT NULL, create_time DATETIME );3. 消息表 message作用:保存聊天历史记录用于查看聊天记录离线消息补偿消息查询表结构字段类型说明idINT消息编号sender_idINT发送者idreceiver_idINT接收者idcontentTEXT消息内容send_timeDATETIME发送时间CREATE TABLE message( id INT PRIMARY KEY AUTO_INCREMENT, sender_id INT NOT NULL, receiver_id INT NOT NULL, content TEXT, send_time DATETIME );查询Jack和Tom聊天记录SELECT * FROM message WHERE (sender_id1 AND receiver_id2) OR (sender_id2 AND receiver_id1) ORDER BY send_time;4. 群成员表 group_member作用:保存群组和用户之间的关系。例如群1001 成员: jack tom lucy表结构字段类型说明idINT编号group_idINT群iduser_idINT用户idroleINT成员身份CREATE TABLE group_member( id INT PRIMARY KEY AUTO_INCREMENT, group_id INT NOT NULL, user_id INT NOT NULL, role INT DEFAULT 0 );3: Redis基础及在聊天室中的应用1 Redis基本概念Redis采用key-value键值对方式存储数据类似C​ unordered_mapstring,string ​- map[username]jack;2 聊天室中Redis常用数据结构:类型特点聊天室应用String字符串验证码、在线状态Hash对象存储用户信息List列表离线消息Set集合好友列表1 String1基础创建数据:SETusername jack查询:GETusername jack删除:DELusername jack2聊天室中应用保存验证码SETEX verify:jack 300 123456 //jack的验证码是123456,300s后过期,自动删除2 Hash1基础HSETuser:jack username jackHGETuser:jack passwordHGETALLuser:jackHEXISTSuser:tom2聊天室中应用保存用户基本信息// user:10001 // username jack // password 123456 // email xxx HSET user:10001 username jack HSET user:10001 password 123456 HSET user:10001 email xxx3 List类似:C队列 queuestringList类似双端队列可以实现消息队列功能1基础添加:LPUSHoffline:jack hello (从左加)-永远先看到最新消息-朋友圈RPUSHoffline:jack hi (从右加)-新的消息在后-聊天室离线消息删除:LPOPoffline:jack (从offline:jack的List里面删除并取出最左边的一条消息)注:聊天室常用RPUSHLPOP-先入先出查看:LRANGEoffline:jack 0 -1 (list range,查看list中的一段数据)这里表示获取jack离线信息中,从第一个元素到最后一个元素2聊天室中应用保存离线消息​ //B离线 //A给B发送 hi~ 服务器: RPUSH offline:B A:hi~ //接着,C给B发送 你在干嘛? 服务器: RPUSH offline:B C:你在干嘛? //B上线后,服务器: LRANGE offline:B 0 -1 //发送给客户端,B看到: A:hi~ C:你在干嘛? ​4 Set相当于C中unordered_set特点:无序,不重复在聊天室中,根据好友列表,判断私聊是否合法(好友列表不是直接存储的而是由好友关系表动态查询得到。MySQL保存用户之间的关系服务器根据用户id查询friend表生成好友列表返回给客户端)添加:SADDfriend:jack tom查看:SISMEMBERSfriend:jack tom-set is member,查看是不是成员,即判断是否存在.返回1是好友SMEMBERSfriend:jack-set members,获取整个集合删除:SREM(set remove,删除集合中的元素)eg:tom和jack删除好友时,需要:SREM friends:tom jackSREM friends:jack tom4: C程序和数据库之间的通信现在,从数据库知识进入项目实现聊天室的C服务器代码怎么把一个C变量传递给MySQL/Redis让数据库真正保存数据核心逻辑:C聊天室程序 → 发送SQL → MySQL仓库装上驱动库C 就拥有了发送 SQL 的能力伪代码模拟流程:(示例为了展示流程使用字符串拼接实际项目使用预处理语句)// 1.程序启动和MySQL建立连接 连接MySQL(127.0.0.1,root,123456,chatroom); // 2.收到客户端注册信息 string name jack; string pwd 123456; // 3.拼凑SQL指令纸条 string sql INSERT INTO user(username,password) VALUES(name,pwd);; // 4.发送纸条给MySQL 发送SQL(sql); // 5.接收MySQL的回信 if(执行成功){ 通知客户端注册成功 }else{ 通知客户端注册失败 }即:MySQL 是独立运行的程序相当于一个仓库。C 程序本身不能直接操作数据库。C 需要借助驱动库把业务数据拼装成我们熟悉的 SQL 字符串把这条 SQL 发送给 MySQL 服务。MySQL 识别 SQL 语句完成增删改查同时利用主键、唯一约束等规则校验数据是否合法最后把执行结果回传给 C 服务端与之相似,C通过Redis客户端库(redis-plus-plus/hiredis)发送Redis命令以MySQL为例,体会:代码:C程序接收用户名和密码然后保存到MySQL的user表中1mysql准备:mysql -u root -pCREATE DATABASE test_chat;USE test_chat;create table user( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL, password VARCHAR(50) NOT NULL );2c程序:文件:mysql_test.cpp代码:#include bits/stdc.h #include string #include mysql/mysql.h using namespace std; int main(){ // 1.初始化mysql句柄 MYSQL* mysql mysql_init(nullptr); if (mysql nullptr){ cout mysql init error endl; return -1; } // 2.建立连接 地址,用户名,密码,数据库名,端口 if (!mysql_real_connect(mysql, 127.0.0.1, root, 0527985, test_chat, 3306, nullptr, 0)){ cout connect mysql error: mysql_error(mysql) endl; mysql_close(mysql); return -1; } cout mysql connect success endl; // 3.接收用户输入模拟聊天室客户端注册 string username; string password; cout 请输入用户名; cin username; cout 请输入密码; cin password; // 4.拼接插入SQL简易演示正式项目要用预处理防止注入 string sql INSERT INTO user(username,password) VALUES( username , password );; // 5.执行SQL int ret mysql_query(mysql, sql.c_str()); if (ret ! 0) cout 执行SQL失败: mysql_error(mysql) endl; else cout 注册数据写入数据库成功 endl; // 关闭连接 mysql_close(mysql); return 0; }3编译运行:g mysql_test.cpp \-o mysql_test \-lmysqlclient./mysql_test4结果:输入:mysql connect success请输入用户名:jack请输入密码:123456查看数据库:SELECT * FROM user;5: 总结ChatServer|------------------| |MySQL Redis长期数据 实时数据用户信息 在线状态好友关系 离线消息历史记录 验证码MySQL负责聊天室中需要长期保存的数据Redis负责聊天室中高频访问、实时变化的数据两者结合实现高性能即时通讯系统。