微服务通讯系统(2)

  • 软件设计及核心代码展示
  • 数据库表设计,ES搜索表设计,Redis键值对设计
  1. 数据库表设计

(1)用户表设计

这里的ID是指的是在系统中用户是第几个注册的(从1开始)

user_id是指用户的唯一ID是通过uuid()函数生成的一串数字(会与第一个ID有点冗余)

Nickname是用户的昵称

Description是用户的一个简介

Password是用户的密码

Phone是用户的电话号码

avatar_id是用户的头像ID(会通过这个ID找到对应在服务端的文件头像)

这张表对对应的C++类如下

private:

friend class odb::access;

#pragma db id auto

unsigned long _id;

#pragma db type("varchar(64)") index unique

std::string _user_id;

#pragma db type("varchar(64)") index unique

odb::nullable<std::string> _nickname; //用户昵称-不一定存在

odb::nullable<std::string> _description; //用户签名 - 不一定存在

#pragma db type("varchar(64)")

odb::nullable<std::string> _password; //用户密码 - 不一定存在

#pragma db type("varchar(64)") index unique

odb::nullable<std::string> _phone; //用户手机号 - 不一定存在

#pragma db type("varchar(64)")

odb::nullable<std::string> _avatar_id; //用户头像文件ID - 不一定存在

  1. 聊天会话表

ID是指每个会话在数据库中的创建次序(从1开始)

chat_session_id是指这个会话通过uuid()函数生成的唯一字符串

chat_session_name是指会话名字

chat_session_id是指会话的类型(群聊会话还是单聊会话)

它所对应的C++类

private:

friend class odb::access;

#pragma db id auto

unsigned long _id;

#pragma db type("varchar(64)") index unique

std::string _chat_session_id;

#pragma db type("varchar(64)")

std::string _chat_session_name;

#pragma db type("tinyint")

ChatSessionType _chat_session_type; //1-单聊; 2-群聊

  1. 聊天会话成员表

ID和前面的一样

session_id每个会话的ID,和上一张表的回话ID对应

user_id用户ID

所对应的C++类

private:

friend class odb::access;

#pragma db id auto

unsigned long _id;

#pragma db type("varchar(64)") index

std::string _session_id;

#pragma db type("varchar(64)")

std::string _user_id;

  1. 聊天消息表

message_id是消息的一个唯一ID,通过uuid()生成

Session_id是消息所属于那个的回话的ID

user_id是消息发送者的ID

message_type是指消息的类型(文字消息,图片消息,文件消息,语音消息)

create_time消息创建时间

Content信息内容(只有文字消息才有)

file_id文件ID(只有图片,文件,语音消息才有)

file_name文件名字(只有图片,文件,语音消息才有)

file_size文件大小(只有图片,文件,语音消息才有)

对应的C++类

private:

friend class odb::access;

#pragma db id auto

unsigned long _id;

#pragma db type("varchar(64)") index unique

std::string _message_id;

#pragma db type("varchar(64)") index

std::string _session_id; //所属会话ID

#pragma db type("varchar(64)")

std::string _user_id; //发送者用户ID

unsigned char _message_type; //消息类型 0-文本;1-图片;2-文件;3-语音

#pragma db type("TIMESTAMP")

boost::posix_time::ptime _create_time; //消息的产生时间

odb::nullable<std::string> _content; //文本消息内容--非文本消息可以忽略

#pragma db type("varchar(64)")

odb::nullable<std::string> _file_id; //文件消息的文件ID -- 文本消息忽略

#pragma db type("varchar(128)")

odb::nullable<std::string> _file_name; //文件消息的文件名称 -- 只针对文件消息有效

odb::nullable<unsigned int> _file_size; //文件消息的文件大小 -- 只针对文件消息有效

  1. 关系表

User_id用户的ID

peer_id用户ID对应的好友的ID(表是双向存在的,有用户添加成功时,要同时添加两条数据)

private:

friend class odb::access;

#pragma db id auto

unsigned long _id;

#pragma db type("varchar(64)") index

std::string _user_id;

#pragma db type("varchar(64)")

std::string _peer_id;

  1. 好友申请表

user_id发起请求的用户ID;

peer_id接收请求的用户ID

Event_id本次事件的ID(当事件被peer_id处理以后,无论是同意或者拒绝,事件都会被删除)

private:

friend class odb::access;

#pragma db id auto

unsigned long _id;

#pragma db type("varchar(64)") index

std::string _user_id;

#pragma db type("varchar(64)") index

std::string _peer_id;

#pragma db type("varchar(64)") index unique

std::string _event_id;

  1. ES搜索表设计

因为用户主要是搜索其他用户和历史消息,所以ES搜索引擎中只存储了这两类搜索

{

"mappings": {

"properties": {

"user_id": {

"type": "keyword",

"fields": {

"standard": {

"type": "text",

"analyzer": "standard"

}

}

},

"nickname": {

"type": "text"

},

"phone": {

"type": "keyword",

"fields": {

"standard": {

"type": "text",

"analyzer": "standard"

}

}

},

"description": {

"type": "text",

"analyzer": "standard"

},

"avatar_id": {

"type": "keyword",

"fields": {

"standard": {

"type": "text",

"analyzer": "standard"

}

}

}

}

}

}

上面是创建user信息的ES索引json映射,内容含有和数据库里面的user表一样

{

"mappings": {

"properties": {

"user_id": {

"type": "keyword",

"fields": {

"standard": {

"type": "text",

"analyzer": "standard"

}

}

},

"message_id": {

"type": "keyword",

"fields": {

"standard": {

"type": "text",

"analyzer": "standard"

}

}

},

"create_time": {

"type": "long"

},

"chat_session_id": {

"type": "keyword",

"fields": {

"standard": {

"type": "text",

"analyzer": "standard"

}

}

},

"content": {

"type": "text"

}

}

}

}

上面是创建message信息的ES索引json映射,内容含有和数据库里面的message表一样

  1. Redis键值对设计

这是session键值对的设计,主要记录了当一个用户登录时,系统会为他分配一个会话ID

class Session {

public:

using ptr = std::shared_ptr<Session>;

Session(const std::shared_ptr<sw::redis::Redis> &redis_client):

_redis_client(redis_client){}

void append(const std::string &ssid, const std::string &uid) {

_redis_client->set(ssid, uid);

}

void remove(const std::string &ssid) {

_redis_client->del(ssid);

}

sw::redis::OptionalString uid(const std::string &ssid) {

return _redis_client->get(ssid);

}

private:

std::shared_ptr<sw::redis::Redis> _redis_client;

};

这是状态键值对的设计,主要是和会话键值对配合使用,当用户登录时,状态键值对会将用户添加,表示用户已经登录,当其他地方有同一个用户登录时就会查询到并拒绝

class Status {

public:

using ptr = std::shared_ptr<Status>;

Status(const std::shared_ptr<sw::redis::Redis> &redis_client):

_redis_client(redis_client){}

void append(const std::string &uid) {

_redis_client->set(uid, "");

}

void remove(const std::string &uid) {

_redis_client->del(uid);

}

bool exists(const std::string &uid) {

auto res = _redis_client->get(uid);

if (res) return true;

return false;

}

private:

std::shared_ptr<sw::redis::Redis> _redis_client;

};

这是验证码键值对,当用户请求发送验证码时,验证码就会记录在这里一份,拿出来和用户发的验证码进行比较,一定时间后会自动删除

class Codes {

public:

using ptr = std::shared_ptr<Codes>;

Codes(const std::shared_ptr<sw::redis::Redis> &redis_client):

_redis_client(redis_client){}

void append(const std::string &cid, const std::string &code,

const std::chrono::milliseconds &t = std::chrono::milliseconds(300000)) {

_redis_client->set(cid, code, t);

}

void remove(const std::string &cid) {

_redis_client->del(cid);

}

sw::redis::OptionalString code(const std::string &cid) {

return _redis_client->get(cid);

}

private:

std::shared_ptr<sw::redis::Redis> _redis_client;

};

相关推荐
Σίσυφος190012 分钟前
halcon 条形码、二维码识别、opencv识别
前端·数据库
Dream it possible!22 分钟前
LeetCode 热题 100_在排序数组中查找元素的第一个和最后一个位置(65_34_中等_C++)(二分查找)(一次二分查找+挨个搜索;两次二分查找)
c++·算法·leetcode
柠石榴28 分钟前
【练习】【回溯No.1】力扣 77. 组合
c++·算法·leetcode·回溯
王老师青少年编程30 分钟前
【GESP C++八级考试考点详细解读】
数据结构·c++·算法·gesp·csp·信奥赛
小刘|1 小时前
深入理解 SQL 注入漏洞及解决方案
数据库·sql
天上掉下来个程小白2 小时前
案例-14.文件上传-简介
数据库·spring boot·后端·mybatis·状态模式
哆木2 小时前
排查生产sql查询缓慢
数据库·sql·mysql
澄澈天空2 小时前
C++ MFC添加RichEditControl控件后,程序启动失败
c++·mfc
橘子师兄2 小时前
分页功能组件开发
数据库·python·django
Lzc7743 小时前
C++初阶——简单实现vector
c++·简单实现vector