|
|
|
@ -35,24 +35,24 @@ func OpenRedisConn(target []string, auth_type, passwd string, isCluster bool, tl |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func OpenRedisConnWithTimeout(target []string, auth_type, passwd string, readTimeout, writeTimeout time.Duration, |
|
|
|
|
isCluster bool, tlsEnable bool) redigo.Conn { |
|
|
|
|
// return redigo.NewConn(OpenNetConn(target, auth_type, passwd), readTimeout, writeTimeout)
|
|
|
|
|
isCluster bool, tlsEnable bool) redigo.Conn { |
|
|
|
|
if isCluster { |
|
|
|
|
// the alive time isn't the tcp keep_alive parameter
|
|
|
|
|
cluster, err := redigoCluster.NewCluster( |
|
|
|
|
&redigoCluster.Options{ |
|
|
|
|
StartNodes: target, |
|
|
|
|
ConnTimeout: 30 * time.Second, |
|
|
|
|
ConnTimeout: 5 * time.Second, |
|
|
|
|
ReadTimeout: readTimeout, |
|
|
|
|
WriteTimeout: writeTimeout, |
|
|
|
|
KeepAlive: 16, |
|
|
|
|
AliveTime: time.Duration(conf.Options.KeepAlive) * time.Second, |
|
|
|
|
KeepAlive: 32, // number of available connections
|
|
|
|
|
AliveTime: 10 * time.Second, // hard code to set alive time in single connection, not the tcp keep alive
|
|
|
|
|
Password: passwd, |
|
|
|
|
}) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Panicf("create cluster connection error[%v]", err) |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
return NewClusterConn(cluster, 4096) |
|
|
|
|
return NewClusterConn(cluster, RecvChanSize) |
|
|
|
|
} else { |
|
|
|
|
// tls only support single connection currently
|
|
|
|
|
return redigo.NewConn(OpenNetConn(target[0], auth_type, passwd, tlsEnable), readTimeout, writeTimeout) |
|
|
|
@ -389,14 +389,16 @@ func restoreQuicklistEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) error { |
|
|
|
|
//read type
|
|
|
|
|
var err error |
|
|
|
|
r := rdb.NewRdbReader(bytes.NewReader(e.Value)) |
|
|
|
|
t, err := r.ReadByte() |
|
|
|
|
if err != nil { |
|
|
|
|
log.PanicError(err, "read rdb ") |
|
|
|
|
} |
|
|
|
|
log.Info("restore big key ", string(e.Key), " Value Length ", len(e.Value), " type ", t) |
|
|
|
|
|
|
|
|
|
log.Debug("restore big key ", string(e.Key), " Value Length ", len(e.Value), " type ", t) |
|
|
|
|
count := 0 |
|
|
|
|
switch t { |
|
|
|
|
case rdb.RdbTypeHashZiplist: |
|
|
|
@ -422,7 +424,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
log.PanicError(err, "read rdb ") |
|
|
|
|
} |
|
|
|
|
count++ |
|
|
|
|
c.Send("HSET", e.Key, field, value) |
|
|
|
|
err = c.Send("HSET", e.Key, field, value) |
|
|
|
|
if (count == 100) || (i == (length - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -455,7 +457,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
log.PanicError(err, "read rdb ") |
|
|
|
|
} |
|
|
|
|
count++ |
|
|
|
|
c.Send("ZADD", e.Key, scoreBytes, member) |
|
|
|
|
err = c.Send("ZADD", e.Key, scoreBytes, member) |
|
|
|
|
if (count == 100) || (i == (cardinality - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -500,7 +502,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
intString = strconv.FormatInt(int64(int64(binary.LittleEndian.Uint64(intBytes))), 10) |
|
|
|
|
} |
|
|
|
|
count++ |
|
|
|
|
c.Send("SADD", e.Key, []byte(intString)) |
|
|
|
|
err = c.Send("SADD", e.Key, []byte(intString)) |
|
|
|
|
if (count == 100) || (i == (cardinality - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -525,7 +527,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
} |
|
|
|
|
//rpush(c, e.Key, entry)
|
|
|
|
|
count++ |
|
|
|
|
c.Send("RPUSH", e.Key, entry) |
|
|
|
|
err = c.Send("RPUSH", e.Key, entry) |
|
|
|
|
if (count == 100) || (i == (length - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -562,7 +564,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
log.PanicError(err, "read rdb ") |
|
|
|
|
} |
|
|
|
|
count++ |
|
|
|
|
c.Send("HSET", e.Key, field, value) |
|
|
|
|
err = c.Send("HSET", e.Key, field, value) |
|
|
|
|
if (count == 100) || (i == (int(length) - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -587,7 +589,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
} |
|
|
|
|
//rpush(c, e.Key, field)
|
|
|
|
|
count++ |
|
|
|
|
c.Send("RPUSH", e.Key, field) |
|
|
|
|
err = c.Send("RPUSH", e.Key, field) |
|
|
|
|
if (count == 100) || (i == (int(n) - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -605,7 +607,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
log.PanicError(err, "read rdb ") |
|
|
|
|
} |
|
|
|
|
count++ |
|
|
|
|
c.Send("SADD", e.Key, member) |
|
|
|
|
err = c.Send("SADD", e.Key, member) |
|
|
|
|
if (count == 100) || (i == (int(n) - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -633,8 +635,9 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
log.PanicError(err, "read rdb ") |
|
|
|
|
} |
|
|
|
|
count++ |
|
|
|
|
log.Info("restore big zset key ", string(e.Key), " score ", (Float64ToByte(score)), " member ", string(member)) |
|
|
|
|
c.Send("ZADD", e.Key, Float64ToByte(score), member) |
|
|
|
|
log.Info("restore big zset key ", string(e.Key), " score ", Float64ToByte(score), |
|
|
|
|
" member ", string(member)) |
|
|
|
|
err = c.Send("ZADD", e.Key, Float64ToByte(score), member) |
|
|
|
|
if (count == 100) || (i == (int(n) - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -671,7 +674,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
} |
|
|
|
|
//hset(c, e.Key, field, value)
|
|
|
|
|
count++ |
|
|
|
|
c.Send("HSET", e.Key, field, value) |
|
|
|
|
err = c.Send("HSET", e.Key, field, value) |
|
|
|
|
if (count == 100) || (i == (int(n) - 1)) { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -701,7 +704,7 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
} |
|
|
|
|
log.Info("rpush key: ", e.Key, " value: ", entry) |
|
|
|
|
count++ |
|
|
|
|
c.Send("RPUSH", e.Key, entry) |
|
|
|
|
err = c.Send("RPUSH", e.Key, entry) |
|
|
|
|
if count == 100 { |
|
|
|
|
flushAndCheckReply(c, count) |
|
|
|
|
count = 0 |
|
|
|
@ -715,6 +718,8 @@ func restoreBigRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
default: |
|
|
|
|
log.PanicError(fmt.Errorf("can't deal rdb type:%d", t), "restore big key fail") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func RestoreRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
@ -793,7 +798,11 @@ func RestoreRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
log.Panicf("del ", string(e.Key), err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
restoreBigRdbEntry(c, e) |
|
|
|
|
|
|
|
|
|
if err := restoreBigRdbEntry(c, e); err != nil { |
|
|
|
|
log.Panic(err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if e.ExpireAt != 0 { |
|
|
|
|
r, err := redigo.Int64(c.Do("pexpire", e.Key, ttlms)) |
|
|
|
|
if err != nil && r != 1 { |
|
|
|
@ -816,6 +825,7 @@ func RestoreRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
log.Debugf("restore key[%s] with params[%v]", e.Key, params) |
|
|
|
|
// fmt.Printf("key: %v, value: %v params: %v\n", string(e.Key), e.Value, params)
|
|
|
|
|
// s, err := redigo.String(c.Do("restore", params...))
|
|
|
|
|
RESTORE: |
|
|
|
|
s, err := redigoCluster.String(c.Do("restore", params...)) |
|
|
|
|
if err != nil { |
|
|
|
|
/*The reply value of busykey in 2.8 kernel is "target key name is busy", |
|
|
|
@ -826,21 +836,27 @@ func RestoreRdbEntry(c redigo.Conn, e *rdb.BinEntry) { |
|
|
|
|
if !conf.Options.Metric { |
|
|
|
|
log.Infof("warning, rewrite key: %v", string(e.Key)) |
|
|
|
|
} |
|
|
|
|
var s2 string |
|
|
|
|
var rerr error |
|
|
|
|
|
|
|
|
|
if conf.Options.TargetReplace { |
|
|
|
|
params = append(params, "REPLACE") |
|
|
|
|
s2, rerr = redigo.String(c.Do("restore", params...)) |
|
|
|
|
} else { |
|
|
|
|
_, _ = redigo.String(c.Do("del", e.Key)) |
|
|
|
|
s2, rerr = redigo.String(c.Do("restore", params...)) |
|
|
|
|
} |
|
|
|
|
if rerr != nil { |
|
|
|
|
log.Info(s2, rerr, "key ", string(e.Key)) |
|
|
|
|
_, err = redigo.String(c.Do("del", e.Key)) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Panicf("delete key[%v] failed[%v]", string(e.Key), err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// retry
|
|
|
|
|
goto RESTORE |
|
|
|
|
} else { |
|
|
|
|
log.Panicf("target key name is busy:", string(e.Key)) |
|
|
|
|
} |
|
|
|
|
} else if strings.Contains(err.Error(), "Bad data format") { |
|
|
|
|
// from big version to small version may has this error. we need to split the data struct
|
|
|
|
|
log.Warnf("return error[%v], ignore it and try to split the value", err) |
|
|
|
|
if err := restoreBigRdbEntry(c, e); err != nil { |
|
|
|
|
log.Panic(err) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
log.PanicError(err, "restore command error key:", string(e.Key), " err:", err.Error()) |
|
|
|
|
} |
|
|
|
|