站内短消息的数据库设计

目前很多的短消息功能都允许群发。在群发数量大的情况下,该如何有效的处理呢?我在工作中遇到这样的问题,参考网上一些方案,想了几种设计方式,记录一下:

1. 全写入
在点击发送时将发送给N个用户的信息以N条记录的方式写入数据库。
修改(已读标记)、删除单一。

2. 1+N条记录
由于是群发,因此文本内容都是相同的。所以设计表结构时分消息表和消息内容表。在提交的时候,先将内容记入消息内容表并获取其id,然后关联该内容id给N个用户分N条写入消息表。
修改单一。
删除:如果收到该消息的用户都删除了该消息的情况下,应该删除消息内容表中的数据。
对于该处目前想到两种方式:
1). 给消息内容表增加个计数,每个用户删除时将计数减1,当计数为0时就可以删除该记录。
2). 删除在消息表中没有对应数据的消息内容。由计划任务定时处理(前种方式的实际数据删除也可采用这种方式)

3. 1+1+N条记录

一条消息内容+1条广播范围+多条receiver信息,查询未读消息时从广播表中查找,receiver信息接收人查看消息时记录。

转载于:https://my.oschina.net/u/168061/blog/52946

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
消息聊天系统MySQL表设计_聊天系统-数据库设计 //常⽤的redis命令 CONFIG SET requirepass "mypass" //Hashmap hset [key] [field] value] hget [key] [field] hgetall [key] //List LPUSH [key] [value] RPUSH [key] [value] LPOP [key] RPOP [key] //删除表头2个值为value的元素 LREM [key] [count > 0] [value] //删除表尾2个值为value的元素 LREM [key] [count < 0] [value] //删除所有值为value的元素 LREM [key] [count = 0] [value] LREM mylist 2 "hello" LREM mylist -2 "hello" //查询0~最后1个元素(不删除) LRANGE mylist 0 -1 BRPOP [key] [timeout] BLPOP [key] [timeout] //例:获取message_1最左的元素,如果没有,等待5秒,超时返回nil BLPOP message_1 5 采⽤Redis进⾏数据存储,主要包括频控、限流、⽤户表、在线⽤户表、聊天消息表(redis list实现消息队列)、好友表(TODO) 频控 CheckFrequency(userId uint64) bool 返回true检查通过,false触发频控 visited_{user_id} >3触发 //频控key前缀 const freqPre string = "visited_" /* Desc: 检查频控key Input: userId Output: False 触发频控/异常 True 正常请求 */ func CheckFrequency(userId uint64) bool { key := freqPre + strconv.FormatUint(userId, 10) resExists, err := Client.Exists(key).Result() if err != nil { return false } if resExists == 0 { //该key不存在 Client.Set(key, 0, 100 * time.Second) return true } res, err := Client.Get(key).Result() if err != nil { return false } resCnt, err := strconv.Atoi(res) if err != nil { return false } if resCnt > 2 {//10秒同⼀userid不能访问超过2次 fmt.Println("触发频控") //... return false } Client.Incr(key) return true } 频控测试 redis.CreateClient() var res bool = true for res { time.Sleep(time.Second * 1) res = redis.CheckFrequency(54508) fmt.Println(res) } 限流 /* 令牌桶算法API */ const LevelFast int = 1 const LevelMedium int = 2 const LevelSlow int = 3 var tokenBucket *ratelimit.Bucket func InitToken(speedLevel int) { var bucketFillDuring time.Duration if speedLevel == LevelFast { bucketFillDuring = 20 * time.Millisecond } else if speedLevel == LevelMedium { bucketFillDuring = 100 * time.Millisecond } else if speedLevel == LevelSlow { bucketFillDuring = 1000 * time.Millisecond } else { //⽇志 fmt.Println("speedLevel只能为Fast, Medium, Slow三个值!") return } var bucketMax int64 = 1//令牌桶最⼤容量,初始也会有这么多个令牌,此处为1是测试所⽤,⽅便看到限流效果,后期需增加⼤⼩ toke
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值