Giter Club home page Giter Club logo

Comments (14)

vczyh avatar vczyh commented on September 26, 2024 1

@vczyh 有道理,但是暂时没时间改。欢迎 PR!

看了下现在的逻辑,感觉不太好改,现在的接口是:

// RedisObject is interface for a redis object
type RedisObject interface {
	LoadFromBuffer(rd io.Reader, key string, typeByte byte)
	Rewrite() []RedisCmd
}

LoadFromBuffer 现在是全部解析:

type SetObject struct {
	key      string
	elements []string
}

我的想法是把 RedisObject 改成类似这样,还是 Set 为例:

type SetObject struct {
	key      string
        r io      Reader
}

func (o *SetObject) Rewrite() chan RedisCmd {
	cmds := make(chan RedisCmd, 100)
	go func() {
		// parse set element
		element := "set element"
		cmd := RedisCmd{"sadd", o.key, element}
		cmds <- cmd
	}()
	return cmds
}

根据命令恢复:

o := types.ParseObject(anotherReader, typeByte, key)
for cmd range o.Rewrite() {
    // send to entry channel
}

因为需要支持 restore 命令恢复,可以在 RedisObject 添加 dump 方法,现在接口变成这样:

type RedisObject interface {
	LoadFromBuffer(rd io.Reader, key string, typeByte byte)
	Rewrite() chan RedisCmd
        DumpTo(w io.Writer) error 
}

from redisshake.

suxb201 avatar suxb201 commented on September 26, 2024

是这样的,很有道理。

from redisshake.

Suarez1024 avatar Suarez1024 commented on September 26, 2024

请问这个有修复计划吗?

from redisshake.

vczyh avatar vczyh commented on September 26, 2024

现在是将所有 element 放到数组中,应该可以改成放到 channel 中

from redisshake.

suxb201 avatar suxb201 commented on September 26, 2024

@vczyh 有道理,但是暂时没时间改。欢迎 PR!

from redisshake.

suxb201 avatar suxb201 commented on September 26, 2024

@vczyh 酷,我认为这是比较优雅的改法。
有两点需要提醒下:

  1. go func() 中需要 close channel,这样外面的 for 循环才可以停止。
  2. 我没明白 DumpTo 的用途,对于从 dump.rdb 中加载出来数据,如果需要解析才走 Rewrite(),否则直接封装为 restore 命令发送至目的端。没有必要解析-编码-封装为 restore 命令。实际上对于多数命令都是不需要解析的,可以直接封装为 restore 命令发送至目的端。只有对于体积很大的 key,一条 restore 命令无法承载,才需要解析,然后重写为 Redis 命令发送。

from redisshake.

vczyh avatar vczyh commented on September 26, 2024

@vczyh 酷,我认为这是比较优雅的改法。 有两点需要提醒下:

  1. go func() 中需要 close channel,这样外面的 for 循环才可以停止。
  2. 我没明白 DumpTo 的用途,对于从 dump.rdb 中加载出来数据,如果需要解析才走 Rewrite(),否则直接封装为 restore 命令发送至目的端。没有必要解析-编码-封装为 restore 命令。实际上对于多数命令都是不需要解析的,可以直接封装为 restore 命令发送至目的端。只有对于体积很大的 key,一条 restore 命令无法承载,才需要解析,然后重写为 Redis 命令发送。
  1. 感谢提醒。
  2. DumpTo 的作用就是 restore 内容,类似这个:
    func (ld *Loader) createValueDump(typeByte byte, val []byte) string {
    ld.dumpBuffer.Reset()
    _, _ = ld.dumpBuffer.Write([]byte{typeByte})
    _, _ = ld.dumpBuffer.Write(val)
    _ = binary.Write(&ld.dumpBuffer, binary.LittleEndian, uint16(6))
    // calc crc
    sum64 := utils.CalcCRC64(ld.dumpBuffer.Bytes())
    _ = binary.Write(&ld.dumpBuffer, binary.LittleEndian, sum64)
    return ld.dumpBuffer.String()
    }

RedisObject 持有 io.Reader 引用,调用 Rewrite 会解析成具体 cmd,调用 DumpTo 会直接拼接内容生成 restore 内容。

from redisshake.

suxb201 avatar suxb201 commented on September 26, 2024

@vczyh 意思是把 createValueDump 方法搬到 RedisObject 内部吗?这样会不会一样的方法要实现多遍。

from redisshake.

vczyh avatar vczyh commented on September 26, 2024

@vczyh 意思是把 createValueDump 方法搬到 RedisObject 内部吗?这样会不会一样的方法要实现多遍。

有道理,那就还是放在外部,就像现在一样:

var value bytes.Buffer
anotherReader := io.TeeReader(rd, &value)
o := types.ParseObject(anotherReader, typeByte, key)

看看还有什么其他问题没?

from redisshake.

suxb201 avatar suxb201 commented on September 26, 2024

@vczyh 没有了。有些不好改的结构也可以保留原有的 rewrite 方式,虽然方法是返回 chan,但是内部可以一次性做完。

from redisshake.

vczyh avatar vczyh commented on September 26, 2024

@vczyh 没有了。有些不好改的结构也可以保留原有的 rewrite 方式,虽然方法是返回 chan,但是内部可以一次性做完。

好的,我有时间改一下~

from redisshake.

vczyh avatar vczyh commented on September 26, 2024

@suxb201 遇到一个问题,虽然现在 o.Rewrite() 返回的是 channel,实现了同时解析和发送,但是 value 字段仍然会存着所有的 RedisObject 数据,仍然占大量内存,这块逻辑怎么优化?最好是直接写入到目标 socket writer。

key := structure.ReadString(rd)
var value bytes.Buffer
anotherReader := io.TeeReader(rd, &value)
o := types.ParseObject(anotherReader, typeByte, key)
if uint64(value.Len()) > config.Opt.Adv anced.TargetRedisProtoMaxBulkLen {
	cmdC := o.Rewrite()
	for cmd := range cmdC {
		e := entry.NewEntry()
		e.DbId = ld.nowDBId
		e.Argv = cmd
		ld.ch <- e
	}
	if ld.expireMs != 0 {
		e := entry.NewEntry()
		e.DbId = ld.nowDBId
		e.Argv = []string{"PEXPIRE", key, strconv.FormatInt(ld.expireMs, 10)}
		ld.ch <- e
	}
}

from redisshake.

suxb201 avatar suxb201 commented on September 26, 2024

我没有想到好的解决方案。
推荐:去掉 TargetRedisProtoMaxBulkLen 配置,无论什么类型统一 Rewrite(),这样可以去掉 TeeReader。可以先这样试着能不能写出来。

from redisshake.

vczyh avatar vczyh commented on September 26, 2024

@suxb201 Review code please.

from redisshake.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.