mirror of
https://github.com/openimsdk/open-im-server.git
synced 2025-11-05 11:52:10 +08:00
seq
This commit is contained in:
parent
fe4842b496
commit
d55d416f68
36
pkg/common/storage/cache/redis/seq.md
vendored
Normal file
36
pkg/common/storage/cache/redis/seq.md
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
### mongo
|
||||||
|
```go
|
||||||
|
type Seq struct {
|
||||||
|
ConversationID string `bson:"conversation_id"`
|
||||||
|
MaxSeq int64 `bson:"max_seq"`
|
||||||
|
MinSeq int64 `bson:"min_seq"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Seq interface {
|
||||||
|
Malloc(ctx context.Context, conversationID string, size int64) (int64, error)
|
||||||
|
GetMaxSeq(ctx context.Context, conversationID string) (int64, error)
|
||||||
|
GetMinSeq(ctx context.Context, conversationID string) (int64, error)
|
||||||
|
SetMinSeq(ctx context.Context, conversationID string, seq int64) error
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Malloc 申请seq数量,返回的已有seq的最大值,消息用的第一个seq是返回值+1
|
||||||
|
2. GetMaxSeq 获取申请的seq的最大值,在发消息的seq小于这个值
|
||||||
|
3. GetMinSeq 获取最小的seq,用于拉取历史消息
|
||||||
|
4. SetMinSeq 设置最小的seq,用于拉取历史消息
|
||||||
|
|
||||||
|
### redis
|
||||||
|
```go
|
||||||
|
type RedisSeq struct {
|
||||||
|
Curr int64 // 当前的最大seq
|
||||||
|
Last int64 // mongodb中申请的最大seq
|
||||||
|
Lock *int64 // 锁,用于在mongodb中申请seq
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Malloc 申请seq数量,返回的已有seq的最大值,消息用的第一个seq是返回值+1,如果redis中申请数量够用,直接返回,并自增对应数量。如果redis中申请数量不够用,加锁,从mongodb中申请seq。
|
||||||
|
2. GetMaxSeq 获取已发消息的最大seq就是Curr的值。如果redis中缓存不存在就通过mongodb获取最大seq。存储在redis中。其中Curr和Last都是这个seq值。
|
||||||
|
3. GetMinSeq, SetMinSeq用之前rockscache的方案。
|
||||||
9
pkg/common/storage/cache/redis/seq1.go
vendored
9
pkg/common/storage/cache/redis/seq1.go
vendored
@ -47,6 +47,12 @@ func NewTestSeq() *SeqMalloc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RedisSeq struct {
|
||||||
|
Curr int64
|
||||||
|
Last int64
|
||||||
|
Lock *int64
|
||||||
|
}
|
||||||
|
|
||||||
type SeqMalloc struct {
|
type SeqMalloc struct {
|
||||||
rdb redis.UniversalClient
|
rdb redis.UniversalClient
|
||||||
mgo database.Seq
|
mgo database.Seq
|
||||||
@ -118,6 +124,7 @@ end
|
|||||||
local curr_seq = tonumber(redis.call("HGET", key, "CURR"))
|
local curr_seq = tonumber(redis.call("HGET", key, "CURR"))
|
||||||
local last_seq = tonumber(redis.call("HGET", key, "LAST"))
|
local last_seq = tonumber(redis.call("HGET", key, "LAST"))
|
||||||
if size == 0 then
|
if size == 0 then
|
||||||
|
redis.call("EXPIRE", key, dataSecond)
|
||||||
table.insert(result, 0)
|
table.insert(result, 0)
|
||||||
table.insert(result, curr_seq)
|
table.insert(result, curr_seq)
|
||||||
table.insert(result, last_seq)
|
table.insert(result, last_seq)
|
||||||
@ -136,6 +143,7 @@ if max_seq > last_seq then
|
|||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
redis.call("HSET", key, "CURR", max_seq)
|
redis.call("HSET", key, "CURR", max_seq)
|
||||||
|
redis.call("EXPIRE", key, dataSecond)
|
||||||
table.insert(result, 0)
|
table.insert(result, 0)
|
||||||
table.insert(result, curr_seq)
|
table.insert(result, curr_seq)
|
||||||
table.insert(result, last_seq)
|
table.insert(result, last_seq)
|
||||||
@ -219,6 +227,7 @@ func (s *SeqMalloc) Malloc(ctx context.Context, conversationID string, size int6
|
|||||||
s.setSeqRetry(ctx, key, states[1], seq+size, seq+mallocSize)
|
s.setSeqRetry(ctx, key, states[1], seq+size, seq+mallocSize)
|
||||||
return seq, nil
|
return seq, nil
|
||||||
case 2: // locked
|
case 2: // locked
|
||||||
|
fmt.Println("locked----->", "conversationID", conversationID, "size", size)
|
||||||
if err := s.wait(ctx); err != nil {
|
if err := s.wait(ctx); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
62
pkg/common/storage/cache/redis/seq_test.go
vendored
62
pkg/common/storage/cache/redis/seq_test.go
vendored
@ -2,22 +2,72 @@ package redis
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSeq(t *testing.T) {
|
func TestSeq(t *testing.T) {
|
||||||
ts := NewTestSeq()
|
ts := NewTestSeq()
|
||||||
for i := 1; i < 1000000; i++ {
|
var (
|
||||||
var size int64 = 100
|
wg sync.WaitGroup
|
||||||
first, err := ts.Malloc(context.Background(), "1", size)
|
speed atomic.Int64
|
||||||
|
)
|
||||||
|
|
||||||
|
const count = 256
|
||||||
|
wg.Add(count)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
index := i + 1
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
var size int64 = 1
|
||||||
|
cID := strconv.Itoa(index * 100)
|
||||||
|
for i := 1; ; i++ {
|
||||||
|
first, err := ts.mgo.Malloc(context.Background(), cID, size) // mongo
|
||||||
|
//first, err := ts.Malloc(context.Background(), cID, size) // redis
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("[%d] %s", i, err)
|
t.Logf("[%d-%d] %s %s", index, i, cID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Logf("[%d] %d -> %d", i, first+1, first+size)
|
speed.Add(size)
|
||||||
time.Sleep(time.Second / 4)
|
_ = first
|
||||||
|
//t.Logf("[%d] %d -> %d", i, first+1, first+size)
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
ticker := time.NewTicker(time.Second)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
ticker.Stop()
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
value := speed.Swap(0)
|
||||||
|
t.Logf("speed: %d/s", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//for i := 1; i < 1000000; i++ {
|
||||||
|
// var size int64 = 100
|
||||||
|
// first, err := ts.Malloc(context.Background(), "1", size)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Logf("[%d] %s", i, err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// t.Logf("[%d] %d -> %d", i, first+1, first+size)
|
||||||
|
// time.Sleep(time.Second / 4)
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDel(t *testing.T) {
|
func TestDel(t *testing.T) {
|
||||||
|
|||||||
@ -349,7 +349,6 @@ func (db *commonMsgDatabase) DeleteMessagesFromCache(ctx context.Context, conver
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) {
|
func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) {
|
||||||
|
|
||||||
// TODO set SEQ
|
// TODO set SEQ
|
||||||
currentMaxSeq, err := db.seq.GetMaxSeq(ctx, conversationID)
|
currentMaxSeq, err := db.seq.GetMaxSeq(ctx, conversationID)
|
||||||
if err != nil && errs.Unwrap(err) != redis.Nil {
|
if err != nil && errs.Unwrap(err) != redis.Nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user