单独拎一个小节来讲消息id,悟了吧
消息id在整个IM即时通讯中,有着关键的作用,消息唯一性、时序性都是依赖消息id完成。
在IM即时通讯中,怎样生成一个消息id?
这不是很简单吗,毫秒级的时间戳就可以了,很不错,一秒钟可以产生1000条消息id,足以应对两个之间的聊天了,但是同一毫秒内多个请求到达,产生的id就不能保证唯一性了。
如果在毫秒的级别上再增加一个自增序列,第一个到达的请求是0,第二个是1,以此次类推...。
毫秒级时间戳+自增序列,确实能满足消息的唯一性和时序性,但前提是机器的时钟不会被回拨以及自增序列并发安全。。
基于"毫秒级时间戳+自增序列"产生的id,这里介绍一个轮子:
snowflake 雪花算法,这是一个分布式唯一ID生成算法,算法生成的id是一个int64类型的整数,64位组成如下:
// snowflake算法生成一个int64类型的id
// 符号位(1bit) + 毫秒级时间(41bit) + 机器id(10bit) + 自增序列(12bit)
// 0 00000000000000000000000000000000000000000 0000000000 000000000000
// 1 + 41 + 10 + 12 = 64由算法可以看出,在一毫秒内,最多可以生成2^22=4194304条id,对于一般的IM来说足够了。
但也有不少眼神犀利小伙子看出了点问题,你有2^10=1024台机器吗?
尴尬了,哪有这么多台机器,能有一台机器只负责产生消息id都不错了,一台机器在一毫秒内,最多能产生2^12=4096条消息id,够用了吗,4096少了点,你就不会安慰下自己吗,1秒=1000毫秒,一秒内可是能产生4096000条消息id,好像也不少了啊,用户多了也不差那点时间去再买台机器,你是不差那点时间吗,你是差那点钱钱吧,又尴尬了
既然是介绍轮子,那肯定是别人造好的呀,有时间造轮子,那还不如花点时间去找找别人造好的轮子。咱不是白飘,咱只是让自己站得更高点而已,虚伪,站得更高不就为了能看到更多轮子吗,这大实话说的,有点意思啊
snowflake算法,golang实现,咳咳,是调用:
package util
import (
"github.com/bwmarrin/snowflake"
)
// snowflake算法生成一个int64类型的id
// 符号位(1bit) + 毫秒级时间(41bit) + 机器id(10bit) + 序列(12bit)
// 0 00000000000000000000000000000000000000000 0000000000 000000000000
// 1 + 41 + 10 + 12 = 64
func MakeSnowflakeID() (int64, error) {
node, err := snowflake.NewNode(0) // 10bit,机器id,0~1023
if err != nil {
return 0, err
}
id := node.Generate()
return id.Int64(), nil
}在这次的IM即时通讯从0到1的实践中,采用的就是snowflake生成消息id。
在IM即时通讯中,在客户端还是服务端生成消息id?
在客户端生成消息id,如果消息id中包含有时间戳那就是不可行的,因为不同客户端所处时区不同,本地的时钟也不同,产生的时间戳没法时序性不可靠;如果产生的消息id,不带时间戳呢,答案是可以的,可以参考微信的消息序列生成。
在服务端生成消息id,相对来说服务端的负压无疑是增加了,但也比较简单,容易维护,这个简单也只是相对而言,一秒内并发达到亿级,再简单的事都会变得很复杂。
在IM即时通讯中,先产生消息,还是先产生消息id?
首先这个问题是针对服务端生成消息id,如果是客户端产生消息id,那他产生消息的同时就可以产生消息id,这个先后顺序无争议点。
先从服务端获取到消息id,再将封装消息后发送到服务端,服务端再将这个消息转发给对方,这个过程要等到msg_id返回才能发送消息出去,慢了

直接将消息发送到服务端,服务端生成消息id并封装到消息体中,再将消息发送给对方,并发回一份给自己。

这种方法看似比较快,但是消息发送方也要等到自己发送的消息返回才能显示出来,也可以直接显示,带加载圈显示,等消息返回后,再去掉加载圈,表示消息发送成功,这里的消息发送成功,仅仅指发送到服务端,并不代表对方能收到,因为服务端发送消息给对端时,可能会失败,想要消息能送达对方,会涉及到一些容错机制以及应答机制,后续会讲到,这里主要是消息id篇幅。
对消息id有啥想法的可在评论区留言,继续去造轮子了,又被发现了,是找轮子
IM即时通讯从0到1的实践,相关文章:
IM即时通讯-消息id(五)<本文>
IM即时通讯-会话列表和会话信箱(六)
IM即时通讯-1.0版成果展示与后续扩展(七)