Skip to content

Commit eae02de

Browse files
smellthemoonlixinguo
and
lixinguo
authored
Change the key to make read faster in rocksmq (milvus-io#26404)
Signed-off-by: lixinguo <[email protected]> Co-authored-by: lixinguo <[email protected]>
1 parent 9484699 commit eae02de

File tree

3 files changed

+222
-31
lines changed

3 files changed

+222
-31
lines changed

internal/kv/rocksdb/rocks_iterator.go

+24
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ func NewRocksIterator(db *gorocksdb.DB, opts *gorocksdb.ReadOptions) *RocksItera
3030
return it
3131
}
3232

33+
func NewRocksIteratorCF(db *gorocksdb.DB, cf *gorocksdb.ColumnFamilyHandle, opts *gorocksdb.ReadOptions) *RocksIterator {
34+
iter := db.NewIteratorCF(opts, cf)
35+
it := &RocksIterator{iter, nil, false}
36+
runtime.SetFinalizer(it, func(rocksit *RocksIterator) {
37+
if !rocksit.close {
38+
log.Error("iterator is leaking.. please check")
39+
}
40+
})
41+
return it
42+
}
43+
3344
func NewRocksIteratorWithUpperBound(db *gorocksdb.DB, upperBoundString string, opts *gorocksdb.ReadOptions) *RocksIterator {
3445
upperBound := []byte(upperBoundString)
3546
opts.SetIterateUpperBound(upperBound)
@@ -43,6 +54,19 @@ func NewRocksIteratorWithUpperBound(db *gorocksdb.DB, upperBoundString string, o
4354
return it
4455
}
4556

57+
func NewRocksIteratorCFWithUpperBound(db *gorocksdb.DB, cf *gorocksdb.ColumnFamilyHandle, upperBoundString string, opts *gorocksdb.ReadOptions) *RocksIterator {
58+
upperBound := []byte(upperBoundString)
59+
opts.SetIterateUpperBound(upperBound)
60+
iter := db.NewIteratorCF(opts, cf)
61+
it := &RocksIterator{iter, upperBound, false}
62+
runtime.SetFinalizer(it, func(rocksit *RocksIterator) {
63+
if !rocksit.close {
64+
log.Error("iteratorCF is leaking.. please check")
65+
}
66+
})
67+
return it
68+
}
69+
4670
// Valid returns false only when an Iterator has iterated past either the
4771
// first or the last key in the database.
4872
func (iter *RocksIterator) Valid() bool {

internal/mq/mqimpl/rocksmq/server/rocksmq_impl.go

+43-25
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"github.com/milvus-io/milvus/internal/allocator"
3131
"github.com/milvus-io/milvus/internal/kv"
3232
rocksdbkv "github.com/milvus-io/milvus/internal/kv/rocksdb"
33-
"github.com/milvus-io/milvus/pkg/common"
3433
"github.com/milvus-io/milvus/pkg/log"
3534
"github.com/milvus-io/milvus/pkg/mq/msgstream/mqwrapper"
3635
"github.com/milvus-io/milvus/pkg/util/hardware"
@@ -118,6 +117,7 @@ var topicMu = sync.Map{}
118117

119118
type rocksmq struct {
120119
store *gorocksdb.DB
120+
cfh []*gorocksdb.ColumnFamilyHandle
121121
kv kv.BaseKV
122122
idAllocator allocator.Interface
123123
storeMu *sync.Mutex
@@ -222,8 +222,13 @@ func NewRocksMQ(name string, idAllocator allocator.Interface) (*rocksmq, error)
222222
optsStore.IncreaseParallelism(parallelism)
223223
// enable back ground flush
224224
optsStore.SetMaxBackgroundFlushes(1)
225+
// use properties as the column families to store trace id
226+
optsStore.SetCreateIfMissingColumnFamilies(true)
225227

226-
db, err := gorocksdb.OpenDb(optsStore, name)
228+
// db, err := gorocksdb.OpenDb(opts, name)
229+
// use properties as the column families to store trace id
230+
giveColumnFamilies := []string{"default", "properties"}
231+
db, cfHandles, err := gorocksdb.OpenDbColumnFamilies(optsStore, name, giveColumnFamilies, []*gorocksdb.Options{optsStore, optsStore})
227232
if err != nil {
228233
return nil, err
229234
}
@@ -243,6 +248,7 @@ func NewRocksMQ(name string, idAllocator allocator.Interface) (*rocksmq, error)
243248

244249
rmq := &rocksmq{
245250
store: db,
251+
cfh: cfHandles,
246252
kv: kv,
247253
idAllocator: mqIDAllocator,
248254
storeMu: &sync.Mutex{},
@@ -634,17 +640,17 @@ func (rmq *rocksmq) Produce(topicName string, messages []ProducerMessage) ([]Uni
634640
for i := 0; i < msgLen && idStart+UniqueID(i) < idEnd; i++ {
635641
msgID := idStart + UniqueID(i)
636642
key := path.Join(topicName, strconv.FormatInt(msgID, 10))
637-
batch.Put([]byte(key), messages[i].Payload)
638-
properties, err := json.Marshal(messages[i].Properties)
639-
if err != nil {
640-
log.Warn("properties marshal failed",
641-
zap.Int64("msgID", msgID),
642-
zap.String("topicName", topicName),
643-
zap.Error(err))
644-
return nil, err
643+
batch.PutCF(rmq.cfh[0], []byte(key), messages[i].Payload)
644+
// batch.Put([]byte(key), messages[i].Payload)
645+
if messages[i].Properties != nil {
646+
properties, err := json.Marshal(messages[i].Properties)
647+
if err != nil {
648+
log.Warn("properties marshal failed", zap.Int64("msgID", msgID), zap.String("topicName", topicName),
649+
zap.Error(err))
650+
return nil, err
651+
}
652+
batch.PutCF(rmq.cfh[1], []byte(key), properties)
645653
}
646-
pKey := path.Join(common.PropertiesKey, topicName, strconv.FormatInt(msgID, 10))
647-
batch.Put([]byte(pKey), properties)
648654
msgIDs[i] = msgID
649655
msgSizes[msgID] = int64(len(messages[i].Payload))
650656
}
@@ -777,8 +783,10 @@ func (rmq *rocksmq) Consume(topicName string, groupName string, n int) ([]Consum
777783
readOpts := gorocksdb.NewDefaultReadOptions()
778784
defer readOpts.Destroy()
779785
prefix := topicName + "/"
780-
iter := rocksdbkv.NewRocksIteratorWithUpperBound(rmq.store, typeutil.AddOne(prefix), readOpts)
786+
iter := rocksdbkv.NewRocksIteratorCFWithUpperBound(rmq.store, rmq.cfh[0], typeutil.AddOne(prefix), readOpts)
787+
iterProperty := rocksdbkv.NewRocksIteratorCFWithUpperBound(rmq.store, rmq.cfh[1], typeutil.AddOne(prefix), readOpts)
781788
defer iter.Close()
789+
defer iterProperty.Close()
782790

783791
var dataKey string
784792
if currentID == DefaultMessageID {
@@ -787,30 +795,39 @@ func (rmq *rocksmq) Consume(topicName string, groupName string, n int) ([]Consum
787795
dataKey = path.Join(topicName, strconv.FormatInt(currentID, 10))
788796
}
789797
iter.Seek([]byte(dataKey))
798+
iterProperty.Seek([]byte(dataKey))
799+
790800
consumerMessage := make([]ConsumerMessage, 0, n)
791801
offset := 0
802+
792803
for ; iter.Valid() && offset < n; iter.Next() {
793804
key := iter.Key()
794805
val := iter.Value()
795806
strKey := string(key.Data())
796807
key.Free()
797-
offset++
808+
properties := make(map[string]string)
809+
var propertiesValue []byte
810+
798811
msgID, err := strconv.ParseInt(strKey[len(topicName)+1:], 10, 64)
799812
if err != nil {
800813
val.Free()
801814
return nil, err
802815
}
803-
askedProperties := path.Join(common.PropertiesKey, topicName, strconv.FormatInt(msgID, 10))
804-
opts := gorocksdb.NewDefaultReadOptions()
805-
defer opts.Destroy()
806-
propertiesValue, err := rmq.store.GetBytes(opts, []byte(askedProperties))
807-
if err != nil {
808-
return nil, err
816+
offset++
817+
818+
if iterProperty.Valid() && string(iterProperty.Key().Data()) == string(iter.Key().Data()) {
819+
// the key of properties is the same with the key of payload
820+
// to prevent mix message with or without property column family
821+
propertiesValue = iterProperty.Value().Data()
822+
iterProperty.Next()
809823
}
810-
properties := make(map[string]string)
824+
825+
// between 2.2.0 and 2.3.0, the key of Payload is topic/properties/msgid/Payload
826+
// will ingnore the property before 2.3.0, just make sure property empty is ok for 2.3
827+
828+
// before 2.2.0, there have no properties in ProducerMessage and ConsumerMessage in rocksmq
829+
// when produce before 2.2.0, but consume after 2.2.0, propertiesValue will be []
811830
if len(propertiesValue) != 0 {
812-
// before 2.2.0, there have no properties in ProducerMessage and ConsumerMessage in rocksmq
813-
// when produce before 2.2.0, but consume in 2.2.0, propertiesValue will be []
814831
if err = json.Unmarshal(propertiesValue, &properties); err != nil {
815832
return nil, err
816833
}
@@ -1008,11 +1025,11 @@ func (rmq *rocksmq) SeekToLatest(topicName, groupName string) error {
10081025
func (rmq *rocksmq) getLatestMsg(topicName string) (int64, error) {
10091026
readOpts := gorocksdb.NewDefaultReadOptions()
10101027
defer readOpts.Destroy()
1011-
iter := rocksdbkv.NewRocksIterator(rmq.store, readOpts)
1028+
iter := rocksdbkv.NewRocksIteratorCF(rmq.store, rmq.cfh[0], readOpts)
10121029
defer iter.Close()
10131030

10141031
prefix := topicName + "/"
1015-
// seek to the last message of thie topic
1032+
// seek to the last message of the topic
10161033
iter.SeekForPrev([]byte(typeutil.AddOne(prefix)))
10171034

10181035
// if iterate fail
@@ -1037,6 +1054,7 @@ func (rmq *rocksmq) getLatestMsg(topicName string) (int64, error) {
10371054
}
10381055

10391056
msgID, err := strconv.ParseInt(seekMsgID[len(topicName)+1:], 10, 64)
1057+
10401058
if err != nil {
10411059
return DefaultMessageID, err
10421060
}

0 commit comments

Comments
 (0)