前言https://github.com/hua1995116...这个项目本来是学生时代找工作的实践项目,没想到竟然是它受到了很多关注,star即将破K,这也激励着我不断完善他。一方面对得起注重学习的人,另一方面也想让自己通过慢慢完善一个项目。提高自己。今天给大家带来的是基于Websocket+Node+Redis的未读消息功能,可能更偏向于实战方向。你需要对Websocket和Node.js有一定的了解。当然,不知道的也能看到效果。效果链接(https://www.qiufengh.com/)可能会激起你的学习动力~我会通过自己的思路进行讲解。代码可能不多,但解释了核心逻辑。上面还有一个github地址,有兴趣的可以详细查看。我的想法或多或少有些不成熟,但我还是有脸露脸的。如果大家有什么建议,请多多指教,让我更加完善这部作品。首先大家熟悉的未读消息设计,就是各种聊天时出现的小红点,是强迫症患者必须清理的小圆点,如图?。我将带你实现这样一个功能。由于一对一的方式比较简单,我只考虑多对多的情况,即一个房间里的未读消息(也可以叫群,后面会叫房间),所以设计这样一个功能,总理我把它分成了3类用户。离线用户在线用户在线用户和入群用户离线用户这种场景相当于我们退出微信,但是再次打开房间时,依然可以看到房间内增加的未读消息。在线用户的场景是我们停留在聊天列表页面。当其他人在房间里发消息时,我们可以看到实时增长的未读消息数。场景示例。在线用户和房间用户的场景其实比较常见。当其他人发送新消息时,我们可以实时看到。这时候就不需要标记未读消息了。场景示例。流程图的主要流程可以简化为三部分,分别是用户、推送函数、消息队列。用户可以是消息提供者或消息接收者。这是过程。当然这个过程涉及到更复杂的消息存储,如何推送、获取、同步等问题。下面是这个过程的详细描述。上图流程解释A.房间用户列表存放在Node缓存中(这里的信息也可以存放在Redis中)B.未读消息列表存放在Redis中C.未读消息列表存放在MongoDB中用户1进入首页。用户1进入房间,重置用户在房间1的未读消息,触发更新模块更新B的未读消息列表。用户1给B房间发消息,后台需要获取房间用户列表,判断用户是否在房间内?是的,由于房间内的用户已经阅读了最新消息,因此无需统计。否,如果用户不在房间,更新其未读消息计数从缓存中获取用户的消息进行分发。用户2登录我们的项目并从离线用户更改为在线用户。当用户2登录时,触发查询模块获取他当前在各个房间的未读消息状态。查询模块查询Redis中的未读消息。如果Redis中没有数据,它会继续查询数据库。如果没有数据,它将返回0给用户。Redis缓存会每分钟与数据库同步一次,保证数据持久化。环境节点:8.5.0+Npm:5.3.0+MongoDBRedis为什么是redis?简介Redis是互联网技术领域中应用最为广泛的存储中间件。它是“RemoteDictionaryService”的缩写,是一个高性能的键值数据库。它具有极高的性能、丰富的数据类型、原子和丰富的特性等优点。Redis有以下5种数据结构String—字符串Hash—字典List—列表Set—集合SortedSet—有序集合。要了解有关这5种存储结构的更多信息,您可以查看http://www.runoob。com/w3cnote/redis-use-scene.html安装windowshttp://www.cnblogs.com/jaign/...macbrew安装redisubuntuapt-get安装redisredhatyum安装rediscentoshttps://www.cnblogs.com/zuido...运行客户端redis-cli可视化工具安装windowshttps://pan.baidu.com/s/1kU8sY3Pmachttps://pan.baidu.com/s/10vpd...源码编译http://docs.redisdesktop.com/...项目中的数据结构在本项目中,我们使用String来存储用户的未读消息记录,并使用其incr命令进行自增操作。当我们的websocket连接时,使用Hash结构来存储用户的socket-id。上面说了counting使用的是Redis的Stirng数据结构。在Redis中,我们的计数key-value是这样的。username-roomid-number例如:hua1995116-room1-1我们的Socket-id是一个Hash结构。socketIdusername-socketid示例:socketIdhua1995116-En4ilYqDpk-P5_tzAAAGMongoDB本项目一开始就使用了MongoDB,MongoDB与Node天然匹配的优点这里不再赘述。Node操作MongoDB的模块叫做mongoose。具体的参数方法可以查看官方文档。https://mongoosejs.com/docs/4.x/index.htmlMongoDB下载地址https://www.mongodb.com/downl...可视化下载地址https://github.com/mrvautin/a...Websocket+node实现下面通过前三个用户场景来详细说明实现代码。当离线用户变为在线用户时,客户端在登录时会发送一个登录事件。以下是后台逻辑。//建立连接socket.on('login',async(user)=>{console.log('socketlogin!');const{name}=user;if(!name){return;}socket.name=name;constroomInfo={};//初始化socketIdawaitupdatehCache('socketId',name,socket.id);for(leti=0;i
