mirror of https://github.com/ledisdb/ledisdb.git
Add a new command ledis and move all commands as the sub commands (#382)
* Add a new command ledis and move all commands as the sub commands
This commit is contained in:
parent
3709e1b06a
commit
b245fa4172
|
@ -0,0 +1,335 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/siddontang/goredis"
|
||||||
|
)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var client *goredis.Client
|
||||||
|
var loop int = 0
|
||||||
|
|
||||||
|
func waitBench(c *goredis.PoolConn, cmd string, args ...interface{}) {
|
||||||
|
_, err := c.Do(strings.ToUpper(cmd), args...)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("do %s error %s\n", cmd, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bench(cmd string, f func(c *goredis.PoolConn)) {
|
||||||
|
wg.Add(*clients)
|
||||||
|
|
||||||
|
t1 := time.Now()
|
||||||
|
for i := 0; i < *clients; i++ {
|
||||||
|
go func() {
|
||||||
|
c, _ := client.Get()
|
||||||
|
for j := 0; j < loop; j++ {
|
||||||
|
f(c)
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
t2 := time.Now()
|
||||||
|
|
||||||
|
d := t2.Sub(t1)
|
||||||
|
|
||||||
|
fmt.Printf("%s: %s %0.3f micros/op, %0.2fop/s\n",
|
||||||
|
cmd,
|
||||||
|
d.String(),
|
||||||
|
float64(d.Nanoseconds()/1e3)/float64(*number),
|
||||||
|
float64(*number)/d.Seconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
var kvSetBase int64 = 0
|
||||||
|
var kvGetBase int64 = 0
|
||||||
|
var kvIncrBase int64 = 0
|
||||||
|
var kvDelBase int64 = 0
|
||||||
|
|
||||||
|
func benchSet() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
value := make([]byte, *valueSize)
|
||||||
|
n := atomic.AddInt64(&kvSetBase, 1)
|
||||||
|
waitBench(c, "SET", n, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("set", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchGet() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := atomic.AddInt64(&kvGetBase, 1)
|
||||||
|
waitBench(c, "GET", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("get", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchRandGet() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := rand.Int() % *number
|
||||||
|
waitBench(c, "GET", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("randget", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchDel() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := atomic.AddInt64(&kvDelBase, 1)
|
||||||
|
waitBench(c, "DEL", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("del", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchPushList() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
value := make([]byte, 100)
|
||||||
|
waitBench(c, "RPUSH", "mytestlist", value)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("rpush", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchRangeList10() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "LRANGE", "mytestlist", 0, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("lrange10", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchRangeList50() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "LRANGE", "mytestlist", 0, 50)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("lrange50", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchRangeList100() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "LRANGE", "mytestlist", 0, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("lrange100", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchPopList() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "LPOP", "mytestlist")
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("lpop", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
var hashSetBase int64 = 0
|
||||||
|
var hashIncrBase int64 = 0
|
||||||
|
var hashGetBase int64 = 0
|
||||||
|
var hashDelBase int64 = 0
|
||||||
|
|
||||||
|
func benchHset() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
value := make([]byte, 100)
|
||||||
|
|
||||||
|
n := atomic.AddInt64(&hashSetBase, 1)
|
||||||
|
waitBench(c, "HSET", "myhashkey", n, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("hset", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchHGet() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := atomic.AddInt64(&hashGetBase, 1)
|
||||||
|
waitBench(c, "HGET", "myhashkey", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("hget", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchHRandGet() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := rand.Int() % *number
|
||||||
|
waitBench(c, "HGET", "myhashkey", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("hrandget", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchHDel() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := atomic.AddInt64(&hashDelBase, 1)
|
||||||
|
waitBench(c, "HDEL", "myhashkey", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("hdel", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
var zsetAddBase int64 = 0
|
||||||
|
var zsetDelBase int64 = 0
|
||||||
|
var zsetIncrBase int64 = 0
|
||||||
|
|
||||||
|
func benchZAdd() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
member := make([]byte, 16)
|
||||||
|
n := atomic.AddInt64(&zsetAddBase, 1)
|
||||||
|
waitBench(c, "ZADD", "myzsetkey", n, member)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("zadd", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchZDel() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := atomic.AddInt64(&zsetDelBase, 1)
|
||||||
|
waitBench(c, "ZREM", "myzsetkey", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("zrem", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchZIncr() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
n := atomic.AddInt64(&zsetIncrBase, 1)
|
||||||
|
waitBench(c, "ZINCRBY", "myzsetkey", 1, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("zincrby", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchZRangeByScore() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "ZRANGEBYSCORE", "myzsetkey", 0, rand.Int(), "withscores", "limit", rand.Int()%100, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("zrangebyscore", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchZRangeByRank() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "ZRANGE", "myzsetkey", 0, rand.Int()%100)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("zrange", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchZRevRangeByScore() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "ZREVRANGEBYSCORE", "myzsetkey", 0, rand.Int(), "withscores", "limit", rand.Int()%100, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("zrevrangebyscore", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchZRevRangeByRank() {
|
||||||
|
f := func(c *goredis.PoolConn) {
|
||||||
|
waitBench(c, "ZREVRANGE", "myzsetkey", 0, rand.Int()%100)
|
||||||
|
}
|
||||||
|
|
||||||
|
bench("zrevrange", f)
|
||||||
|
}
|
||||||
|
|
||||||
|
var benchIP *string
|
||||||
|
var benchPort *int
|
||||||
|
var number *int
|
||||||
|
var clients = flag.Int("c", 50, "number of clients")
|
||||||
|
var round = flag.Int("r", 1, "benchmark round number")
|
||||||
|
var valueSize = flag.Int("vsize", 100, "kv value size")
|
||||||
|
var tests = flag.String("t", "set,get,randget,del,lpush,lrange,lpop,hset,hget,hdel,zadd,zincr,zrange,zrevrange,zdel", "only run the comma separated list of tests")
|
||||||
|
|
||||||
|
func CmdBenchmark() {
|
||||||
|
benchIP = flag.String("ip", "127.0.0.1", "redis/ledis/ssdb server ip")
|
||||||
|
number = flag.Int("n", 1000, "request number")
|
||||||
|
benchPort = flag.Int("port", 6380, "redis/ledis/ssdb server port")
|
||||||
|
|
||||||
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *number <= 0 {
|
||||||
|
panic("invalid number")
|
||||||
|
}
|
||||||
|
|
||||||
|
if *clients <= 0 || *number < *clients {
|
||||||
|
panic("invalid client number")
|
||||||
|
}
|
||||||
|
|
||||||
|
loop = *number / *clients
|
||||||
|
|
||||||
|
addr := fmt.Sprintf("%s:%d", *benchIP, *benchPort)
|
||||||
|
|
||||||
|
client = goredis.NewClient(addr, "")
|
||||||
|
client.SetReadBufferSize(10240)
|
||||||
|
client.SetWriteBufferSize(10240)
|
||||||
|
client.SetMaxIdleConns(16)
|
||||||
|
|
||||||
|
for i := 0; i < *clients; i++ {
|
||||||
|
c, _ := client.Get()
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if *round <= 0 {
|
||||||
|
*round = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ts := strings.Split(*tests, ",")
|
||||||
|
|
||||||
|
for i := 0; i < *round; i++ {
|
||||||
|
for _, s := range ts {
|
||||||
|
switch strings.ToLower(s) {
|
||||||
|
case "set":
|
||||||
|
benchSet()
|
||||||
|
case "get":
|
||||||
|
benchGet()
|
||||||
|
case "randget":
|
||||||
|
benchRandGet()
|
||||||
|
case "del":
|
||||||
|
benchDel()
|
||||||
|
case "lpush":
|
||||||
|
benchPushList()
|
||||||
|
case "lrange":
|
||||||
|
benchRangeList10()
|
||||||
|
benchRangeList50()
|
||||||
|
benchRangeList100()
|
||||||
|
case "lpop":
|
||||||
|
benchPopList()
|
||||||
|
case "hset":
|
||||||
|
benchHset()
|
||||||
|
case "hget":
|
||||||
|
benchHGet()
|
||||||
|
benchHRandGet()
|
||||||
|
case "hdel":
|
||||||
|
benchHDel()
|
||||||
|
case "zadd":
|
||||||
|
benchZAdd()
|
||||||
|
case "zincr":
|
||||||
|
benchZIncr()
|
||||||
|
case "zrange":
|
||||||
|
benchZRangeByRank()
|
||||||
|
benchZRangeByScore()
|
||||||
|
case "zrevrange":
|
||||||
|
//rev is too slow in leveldb, rocksdb or other
|
||||||
|
//maybe disable for huge data benchmark
|
||||||
|
benchZRevRangeByRank()
|
||||||
|
benchZRevRangeByScore()
|
||||||
|
case "zdel":
|
||||||
|
benchZDel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("")
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,17 @@
|
||||||
//This file was generated by .tools/generate_commands.py on Sat Oct 28 2017 18:15:49 -0500
|
//This file was generated by .tools/generate_commands.py on Sat Oct 28 2017 18:15:49 -0500
|
||||||
package main
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/peterh/liner"
|
||||||
|
"github.com/siddontang/goredis"
|
||||||
|
)
|
||||||
|
|
||||||
var helpCommands = [][]string{
|
var helpCommands = [][]string{
|
||||||
{"APPEND", "key value", "KV"},
|
{"APPEND", "key value", "KV"},
|
||||||
|
@ -141,3 +153,198 @@ var helpCommands = [][]string{
|
||||||
{"ZTTL", "key", "ZSet"},
|
{"ZTTL", "key", "ZSet"},
|
||||||
{"ZUNIONSTORE", "destkey numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]", "ZSet"},
|
{"ZUNIONSTORE", "destkey numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]", "ZSet"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ip = flag.String("h", "127.0.0.1", "ledisdb server ip (default 127.0.0.1)")
|
||||||
|
var port = flag.Int("p", 6380, "ledisdb server port (default 6380)")
|
||||||
|
var socket = flag.String("s", "", "ledisdb server socket, overwrite ip and port")
|
||||||
|
|
||||||
|
var (
|
||||||
|
line *liner.State
|
||||||
|
historyPath = "/tmp/ledis-cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CmdCli() {
|
||||||
|
var dbn = flag.Int("n", 0, "ledisdb database number(default 0)")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
line = liner.NewLiner()
|
||||||
|
defer line.Close()
|
||||||
|
|
||||||
|
line.SetCtrlCAborts(true)
|
||||||
|
|
||||||
|
setCompletionHandler()
|
||||||
|
loadHisotry()
|
||||||
|
|
||||||
|
defer saveHisotry()
|
||||||
|
|
||||||
|
var addr string
|
||||||
|
if len(*socket) > 0 {
|
||||||
|
addr = *socket
|
||||||
|
} else {
|
||||||
|
addr = fmt.Sprintf("%s:%d", *ip, *port)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := goredis.NewClient(addr, "")
|
||||||
|
c.SetMaxIdleConns(1)
|
||||||
|
sendSelect(c, *dbn)
|
||||||
|
|
||||||
|
reg, _ := regexp.Compile(`'.*?'|".*?"|\S+`)
|
||||||
|
|
||||||
|
prompt := ""
|
||||||
|
|
||||||
|
for {
|
||||||
|
if *dbn > 0 && *dbn < 16 {
|
||||||
|
prompt = fmt.Sprintf("%s[%d]> ", addr, *dbn)
|
||||||
|
} else {
|
||||||
|
prompt = fmt.Sprintf("%s> ", addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd, err := line.Prompt(prompt)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%s\n", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds := reg.FindAllString(cmd, -1)
|
||||||
|
if len(cmds) == 0 {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
line.AppendHistory(cmd)
|
||||||
|
|
||||||
|
args := make([]interface{}, len(cmds[1:]))
|
||||||
|
|
||||||
|
for i := range args {
|
||||||
|
args[i] = strings.Trim(string(cmds[1+i]), "\"'")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := strings.ToLower(cmds[0])
|
||||||
|
if cmd == "help" || cmd == "?" {
|
||||||
|
printHelp(cmds)
|
||||||
|
} else {
|
||||||
|
r, err := c.Do(cmds[0], args...)
|
||||||
|
|
||||||
|
if err == nil && strings.ToLower(cmds[0]) == "select" {
|
||||||
|
*dbn, _ = strconv.Atoi(cmds[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%s", err.Error())
|
||||||
|
} else {
|
||||||
|
if cmd == "info" {
|
||||||
|
printInfo(r.([]byte))
|
||||||
|
} else {
|
||||||
|
printReply(0, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printInfo(s []byte) {
|
||||||
|
fmt.Printf("%s", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printReply(level int, reply interface{}) {
|
||||||
|
switch reply := reply.(type) {
|
||||||
|
case int64:
|
||||||
|
fmt.Printf("(integer) %d", reply)
|
||||||
|
case string:
|
||||||
|
fmt.Printf("%s", reply)
|
||||||
|
case []byte:
|
||||||
|
fmt.Printf("%q", reply)
|
||||||
|
case nil:
|
||||||
|
fmt.Printf("(nil)")
|
||||||
|
case goredis.Error:
|
||||||
|
fmt.Printf("%s", string(reply))
|
||||||
|
case []interface{}:
|
||||||
|
for i, v := range reply {
|
||||||
|
if i != 0 {
|
||||||
|
fmt.Printf("%s", strings.Repeat(" ", level*4))
|
||||||
|
}
|
||||||
|
|
||||||
|
s := fmt.Sprintf("%d) ", i+1)
|
||||||
|
fmt.Printf("%-4s", s)
|
||||||
|
|
||||||
|
printReply(level+1, v)
|
||||||
|
if i != len(reply)-1 {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
fmt.Printf("invalid ledis reply")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printGenericHelp() {
|
||||||
|
msg :=
|
||||||
|
`ledis-cli
|
||||||
|
Type: "help <command>" for help on <command>
|
||||||
|
`
|
||||||
|
fmt.Println(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printCommandHelp(arr []string) {
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Printf("\t%s %s \n", arr[0], arr[1])
|
||||||
|
fmt.Printf("\tGroup: %s \n", arr[2])
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
|
||||||
|
func printHelp(cmds []string) {
|
||||||
|
args := cmds[1:]
|
||||||
|
if len(args) == 0 {
|
||||||
|
printGenericHelp()
|
||||||
|
} else if len(args) > 1 {
|
||||||
|
fmt.Println()
|
||||||
|
} else {
|
||||||
|
cmd := strings.ToUpper(args[0])
|
||||||
|
for i := 0; i < len(helpCommands); i++ {
|
||||||
|
if helpCommands[i][0] == cmd {
|
||||||
|
printCommandHelp(helpCommands[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendSelect(client *goredis.Client, index int) {
|
||||||
|
if index > 16 || index < 0 {
|
||||||
|
index = 0
|
||||||
|
fmt.Println("index out of range, should less than 16")
|
||||||
|
}
|
||||||
|
_, err := client.Do("select", index)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%s\n", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setCompletionHandler() {
|
||||||
|
line.SetCompleter(func(line string) (c []string) {
|
||||||
|
for _, i := range helpCommands {
|
||||||
|
if strings.HasPrefix(i[0], strings.ToLower(line)) {
|
||||||
|
c = append(c, i[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadHisotry() {
|
||||||
|
if f, err := os.Open(historyPath); err == nil {
|
||||||
|
line.ReadHistory(f)
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveHisotry() {
|
||||||
|
if f, err := os.Create(historyPath); err != nil {
|
||||||
|
fmt.Printf("Error writing history file, err: %v", err)
|
||||||
|
} else {
|
||||||
|
line.WriteHistory(f)
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/siddontang/goredis"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CmdDump() {
|
||||||
|
var host = flag.String("host", "127.0.0.1", "ledis server host")
|
||||||
|
var dumpPort = flag.Int("port", 6380, "ledis server port")
|
||||||
|
var sock = flag.String("sock", "", "ledis unix socket domain")
|
||||||
|
var dumpFile = flag.String("o", "./ledis.dump", "dump file to save")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var f *os.File
|
||||||
|
|
||||||
|
if f, err = os.OpenFile(*dumpFile, os.O_CREATE|os.O_WRONLY, 0644); err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
var addr string
|
||||||
|
if len(*sock) != 0 {
|
||||||
|
addr = *sock
|
||||||
|
} else {
|
||||||
|
addr = fmt.Sprintf("%s:%d", *host, *dumpPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := goredis.ConnectWithSize(addr, 16*1024, 4096)
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
|
println("dump begin")
|
||||||
|
|
||||||
|
if err = c.Send("fullsync"); err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.ReceiveBulkTo(f); err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println("dump end")
|
||||||
|
}
|
|
@ -1,332 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/ledisdb/ledisdb/cmd"
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/siddontang/goredis"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ip = flag.String("ip", "127.0.0.1", "redis/ledis/ssdb server ip")
|
|
||||||
var port = flag.Int("port", 6380, "redis/ledis/ssdb server port")
|
|
||||||
var number = flag.Int("n", 1000, "request number")
|
|
||||||
var clients = flag.Int("c", 50, "number of clients")
|
|
||||||
var round = flag.Int("r", 1, "benchmark round number")
|
|
||||||
var valueSize = flag.Int("vsize", 100, "kv value size")
|
|
||||||
var tests = flag.String("t", "set,get,randget,del,lpush,lrange,lpop,hset,hget,hdel,zadd,zincr,zrange,zrevrange,zdel", "only run the comma separated list of tests")
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
|
|
||||||
var client *goredis.Client
|
|
||||||
var loop int = 0
|
|
||||||
|
|
||||||
func waitBench(c *goredis.PoolConn, cmd string, args ...interface{}) {
|
|
||||||
_, err := c.Do(strings.ToUpper(cmd), args...)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("do %s error %s\n", cmd, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func bench(cmd string, f func(c *goredis.PoolConn)) {
|
|
||||||
wg.Add(*clients)
|
|
||||||
|
|
||||||
t1 := time.Now()
|
|
||||||
for i := 0; i < *clients; i++ {
|
|
||||||
go func() {
|
|
||||||
c, _ := client.Get()
|
|
||||||
for j := 0; j < loop; j++ {
|
|
||||||
f(c)
|
|
||||||
}
|
|
||||||
c.Close()
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
t2 := time.Now()
|
|
||||||
|
|
||||||
d := t2.Sub(t1)
|
|
||||||
|
|
||||||
fmt.Printf("%s: %s %0.3f micros/op, %0.2fop/s\n",
|
|
||||||
cmd,
|
|
||||||
d.String(),
|
|
||||||
float64(d.Nanoseconds()/1e3)/float64(*number),
|
|
||||||
float64(*number)/d.Seconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
var kvSetBase int64 = 0
|
|
||||||
var kvGetBase int64 = 0
|
|
||||||
var kvIncrBase int64 = 0
|
|
||||||
var kvDelBase int64 = 0
|
|
||||||
|
|
||||||
func benchSet() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
value := make([]byte, *valueSize)
|
|
||||||
n := atomic.AddInt64(&kvSetBase, 1)
|
|
||||||
waitBench(c, "SET", n, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("set", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchGet() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := atomic.AddInt64(&kvGetBase, 1)
|
|
||||||
waitBench(c, "GET", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("get", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchRandGet() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := rand.Int() % *number
|
|
||||||
waitBench(c, "GET", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("randget", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchDel() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := atomic.AddInt64(&kvDelBase, 1)
|
|
||||||
waitBench(c, "DEL", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("del", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchPushList() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
value := make([]byte, 100)
|
|
||||||
waitBench(c, "RPUSH", "mytestlist", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("rpush", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchRangeList10() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "LRANGE", "mytestlist", 0, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("lrange10", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchRangeList50() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "LRANGE", "mytestlist", 0, 50)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("lrange50", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchRangeList100() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "LRANGE", "mytestlist", 0, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("lrange100", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchPopList() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "LPOP", "mytestlist")
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("lpop", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
var hashSetBase int64 = 0
|
|
||||||
var hashIncrBase int64 = 0
|
|
||||||
var hashGetBase int64 = 0
|
|
||||||
var hashDelBase int64 = 0
|
|
||||||
|
|
||||||
func benchHset() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
value := make([]byte, 100)
|
|
||||||
|
|
||||||
n := atomic.AddInt64(&hashSetBase, 1)
|
|
||||||
waitBench(c, "HSET", "myhashkey", n, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("hset", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchHGet() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := atomic.AddInt64(&hashGetBase, 1)
|
|
||||||
waitBench(c, "HGET", "myhashkey", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("hget", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchHRandGet() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := rand.Int() % *number
|
|
||||||
waitBench(c, "HGET", "myhashkey", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("hrandget", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchHDel() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := atomic.AddInt64(&hashDelBase, 1)
|
|
||||||
waitBench(c, "HDEL", "myhashkey", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("hdel", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
var zsetAddBase int64 = 0
|
|
||||||
var zsetDelBase int64 = 0
|
|
||||||
var zsetIncrBase int64 = 0
|
|
||||||
|
|
||||||
func benchZAdd() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
member := make([]byte, 16)
|
|
||||||
n := atomic.AddInt64(&zsetAddBase, 1)
|
|
||||||
waitBench(c, "ZADD", "myzsetkey", n, member)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("zadd", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchZDel() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := atomic.AddInt64(&zsetDelBase, 1)
|
|
||||||
waitBench(c, "ZREM", "myzsetkey", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("zrem", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchZIncr() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
n := atomic.AddInt64(&zsetIncrBase, 1)
|
|
||||||
waitBench(c, "ZINCRBY", "myzsetkey", 1, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("zincrby", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchZRangeByScore() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "ZRANGEBYSCORE", "myzsetkey", 0, rand.Int(), "withscores", "limit", rand.Int()%100, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("zrangebyscore", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchZRangeByRank() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "ZRANGE", "myzsetkey", 0, rand.Int()%100)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("zrange", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchZRevRangeByScore() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "ZREVRANGEBYSCORE", "myzsetkey", 0, rand.Int(), "withscores", "limit", rand.Int()%100, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("zrevrangebyscore", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchZRevRangeByRank() {
|
|
||||||
f := func(c *goredis.PoolConn) {
|
|
||||||
waitBench(c, "ZREVRANGE", "myzsetkey", 0, rand.Int()%100)
|
|
||||||
}
|
|
||||||
|
|
||||||
bench("zrevrange", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
cmd.CmdBenchmark()
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if *number <= 0 {
|
|
||||||
panic("invalid number")
|
|
||||||
}
|
|
||||||
|
|
||||||
if *clients <= 0 || *number < *clients {
|
|
||||||
panic("invalid client number")
|
|
||||||
}
|
|
||||||
|
|
||||||
loop = *number / *clients
|
|
||||||
|
|
||||||
addr := fmt.Sprintf("%s:%d", *ip, *port)
|
|
||||||
|
|
||||||
client = goredis.NewClient(addr, "")
|
|
||||||
client.SetReadBufferSize(10240)
|
|
||||||
client.SetWriteBufferSize(10240)
|
|
||||||
client.SetMaxIdleConns(16)
|
|
||||||
|
|
||||||
for i := 0; i < *clients; i++ {
|
|
||||||
c, _ := client.Get()
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
if *round <= 0 {
|
|
||||||
*round = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
ts := strings.Split(*tests, ",")
|
|
||||||
|
|
||||||
for i := 0; i < *round; i++ {
|
|
||||||
for _, s := range ts {
|
|
||||||
switch strings.ToLower(s) {
|
|
||||||
case "set":
|
|
||||||
benchSet()
|
|
||||||
case "get":
|
|
||||||
benchGet()
|
|
||||||
case "randget":
|
|
||||||
benchRandGet()
|
|
||||||
case "del":
|
|
||||||
benchDel()
|
|
||||||
case "lpush":
|
|
||||||
benchPushList()
|
|
||||||
case "lrange":
|
|
||||||
benchRangeList10()
|
|
||||||
benchRangeList50()
|
|
||||||
benchRangeList100()
|
|
||||||
case "lpop":
|
|
||||||
benchPopList()
|
|
||||||
case "hset":
|
|
||||||
benchHset()
|
|
||||||
case "hget":
|
|
||||||
benchHGet()
|
|
||||||
benchHRandGet()
|
|
||||||
case "hdel":
|
|
||||||
benchHDel()
|
|
||||||
case "zadd":
|
|
||||||
benchZAdd()
|
|
||||||
case "zincr":
|
|
||||||
benchZIncr()
|
|
||||||
case "zrange":
|
|
||||||
benchZRangeByRank()
|
|
||||||
benchZRangeByScore()
|
|
||||||
case "zrevrange":
|
|
||||||
//rev is too slow in leveldb, rocksdb or other
|
|
||||||
//maybe disable for huge data benchmark
|
|
||||||
benchZRevRangeByRank()
|
|
||||||
benchZRevRangeByScore()
|
|
||||||
case "zdel":
|
|
||||||
benchZDel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println("")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,207 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/ledisdb/ledisdb/cmd"
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/peterh/liner"
|
|
||||||
"github.com/siddontang/goredis"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ip = flag.String("h", "127.0.0.1", "ledisdb server ip (default 127.0.0.1)")
|
|
||||||
var port = flag.Int("p", 6380, "ledisdb server port (default 6380)")
|
|
||||||
var socket = flag.String("s", "", "ledisdb server socket, overwrite ip and port")
|
|
||||||
var dbn = flag.Int("n", 0, "ledisdb database number(default 0)")
|
|
||||||
|
|
||||||
var (
|
|
||||||
line *liner.State
|
|
||||||
historyPath = "/tmp/ledis-cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
cmd.CmdCli()
|
||||||
|
|
||||||
line = liner.NewLiner()
|
|
||||||
defer line.Close()
|
|
||||||
|
|
||||||
line.SetCtrlCAborts(true)
|
|
||||||
|
|
||||||
setCompletionHandler()
|
|
||||||
loadHisotry()
|
|
||||||
|
|
||||||
defer saveHisotry()
|
|
||||||
|
|
||||||
var addr string
|
|
||||||
if len(*socket) > 0 {
|
|
||||||
addr = *socket
|
|
||||||
} else {
|
|
||||||
addr = fmt.Sprintf("%s:%d", *ip, *port)
|
|
||||||
}
|
|
||||||
|
|
||||||
c := goredis.NewClient(addr, "")
|
|
||||||
c.SetMaxIdleConns(1)
|
|
||||||
sendSelect(c, *dbn)
|
|
||||||
|
|
||||||
reg, _ := regexp.Compile(`'.*?'|".*?"|\S+`)
|
|
||||||
|
|
||||||
prompt := ""
|
|
||||||
|
|
||||||
for {
|
|
||||||
if *dbn > 0 && *dbn < 16 {
|
|
||||||
prompt = fmt.Sprintf("%s[%d]> ", addr, *dbn)
|
|
||||||
} else {
|
|
||||||
prompt = fmt.Sprintf("%s> ", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd, err := line.Prompt(prompt)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s\n", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cmds := reg.FindAllString(cmd, -1)
|
|
||||||
if len(cmds) == 0 {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
line.AppendHistory(cmd)
|
|
||||||
|
|
||||||
args := make([]interface{}, len(cmds[1:]))
|
|
||||||
|
|
||||||
for i := range args {
|
|
||||||
args[i] = strings.Trim(string(cmds[1+i]), "\"'")
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := strings.ToLower(cmds[0])
|
|
||||||
if cmd == "help" || cmd == "?" {
|
|
||||||
printHelp(cmds)
|
|
||||||
} else {
|
|
||||||
r, err := c.Do(cmds[0], args...)
|
|
||||||
|
|
||||||
if err == nil && strings.ToLower(cmds[0]) == "select" {
|
|
||||||
*dbn, _ = strconv.Atoi(cmds[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s", err.Error())
|
|
||||||
} else {
|
|
||||||
if cmd == "info" {
|
|
||||||
printInfo(r.([]byte))
|
|
||||||
} else {
|
|
||||||
printReply(0, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printInfo(s []byte) {
|
|
||||||
fmt.Printf("%s", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func printReply(level int, reply interface{}) {
|
|
||||||
switch reply := reply.(type) {
|
|
||||||
case int64:
|
|
||||||
fmt.Printf("(integer) %d", reply)
|
|
||||||
case string:
|
|
||||||
fmt.Printf("%s", reply)
|
|
||||||
case []byte:
|
|
||||||
fmt.Printf("%q", reply)
|
|
||||||
case nil:
|
|
||||||
fmt.Printf("(nil)")
|
|
||||||
case goredis.Error:
|
|
||||||
fmt.Printf("%s", string(reply))
|
|
||||||
case []interface{}:
|
|
||||||
for i, v := range reply {
|
|
||||||
if i != 0 {
|
|
||||||
fmt.Printf("%s", strings.Repeat(" ", level*4))
|
|
||||||
}
|
|
||||||
|
|
||||||
s := fmt.Sprintf("%d) ", i+1)
|
|
||||||
fmt.Printf("%-4s", s)
|
|
||||||
|
|
||||||
printReply(level+1, v)
|
|
||||||
if i != len(reply)-1 {
|
|
||||||
fmt.Printf("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt.Printf("invalid ledis reply")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printGenericHelp() {
|
|
||||||
msg :=
|
|
||||||
`ledis-cli
|
|
||||||
Type: "help <command>" for help on <command>
|
|
||||||
`
|
|
||||||
fmt.Println(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func printCommandHelp(arr []string) {
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Printf("\t%s %s \n", arr[0], arr[1])
|
|
||||||
fmt.Printf("\tGroup: %s \n", arr[2])
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
|
|
||||||
func printHelp(cmds []string) {
|
|
||||||
args := cmds[1:]
|
|
||||||
if len(args) == 0 {
|
|
||||||
printGenericHelp()
|
|
||||||
} else if len(args) > 1 {
|
|
||||||
fmt.Println()
|
|
||||||
} else {
|
|
||||||
cmd := strings.ToUpper(args[0])
|
|
||||||
for i := 0; i < len(helpCommands); i++ {
|
|
||||||
if helpCommands[i][0] == cmd {
|
|
||||||
printCommandHelp(helpCommands[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendSelect(client *goredis.Client, index int) {
|
|
||||||
if index > 16 || index < 0 {
|
|
||||||
index = 0
|
|
||||||
fmt.Println("index out of range, should less than 16")
|
|
||||||
}
|
|
||||||
_, err := client.Do("select", index)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%s\n", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setCompletionHandler() {
|
|
||||||
line.SetCompleter(func(line string) (c []string) {
|
|
||||||
for _, i := range helpCommands {
|
|
||||||
if strings.HasPrefix(i[0], strings.ToLower(line)) {
|
|
||||||
c = append(c, i[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadHisotry() {
|
|
||||||
if f, err := os.Open(historyPath); err == nil {
|
|
||||||
line.ReadHistory(f)
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveHisotry() {
|
|
||||||
if f, err := os.Create(historyPath); err != nil {
|
|
||||||
fmt.Printf("Error writing history file, err: %v", err)
|
|
||||||
} else {
|
|
||||||
line.WriteHistory(f)
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/ledisdb/ledisdb/cmd"
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/siddontang/goredis"
|
|
||||||
)
|
|
||||||
|
|
||||||
var host = flag.String("host", "127.0.0.1", "ledis server host")
|
|
||||||
var port = flag.Int("port", 6380, "ledis server port")
|
|
||||||
var sock = flag.String("sock", "", "ledis unix socket domain")
|
|
||||||
var dumpFile = flag.String("o", "./ledis.dump", "dump file to save")
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
cmd.CmdDump()
|
||||||
|
|
||||||
var err error
|
|
||||||
var f *os.File
|
|
||||||
|
|
||||||
if f, err = os.OpenFile(*dumpFile, os.O_CREATE|os.O_WRONLY, 0644); err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
var addr string
|
|
||||||
if len(*sock) != 0 {
|
|
||||||
addr = *sock
|
|
||||||
} else {
|
|
||||||
addr = fmt.Sprintf("%s:%d", *host, *port)
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err := goredis.ConnectWithSize(addr, 16*1024, 4096)
|
|
||||||
if err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
println("dump begin")
|
|
||||||
|
|
||||||
if err = c.Send("fullsync"); err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = c.ReceiveBulkTo(f); err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
println("dump end")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,62 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/ledisdb/ledisdb/cmd"
|
||||||
"flag"
|
|
||||||
|
|
||||||
"github.com/ledisdb/ledisdb/config"
|
|
||||||
"github.com/ledisdb/ledisdb/ledis"
|
|
||||||
)
|
|
||||||
|
|
||||||
var configPath = flag.String("config", "", "ledisdb config file")
|
|
||||||
var dumpPath = flag.String("dump_file", "", "ledisdb dump file")
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
cmd.CmdLoad()
|
||||||
|
|
||||||
if len(*configPath) == 0 {
|
|
||||||
println("need ledis config file")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := config.NewConfigWithFile(*configPath)
|
|
||||||
if err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*dumpPath) == 0 {
|
|
||||||
println("need dump file")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(cfg.DataDir) == 0 {
|
|
||||||
println("must set data dir")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ldb, err := ledis.Open(cfg)
|
|
||||||
if err != nil {
|
|
||||||
println("ledis open error ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = loadDump(cfg, ldb)
|
|
||||||
ldb.Close()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
println("Load OK")
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadDump(cfg *config.Config, ldb *ledis.Ledis) error {
|
|
||||||
var err error
|
|
||||||
if err = ldb.FlushAll(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = ldb.LoadDumpFile(*dumpPath)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "github.com/ledisdb/ledisdb/cmd"
|
||||||
"flag"
|
|
||||||
|
|
||||||
"github.com/ledisdb/ledisdb/config"
|
|
||||||
"github.com/ledisdb/ledisdb/store"
|
|
||||||
)
|
|
||||||
|
|
||||||
var fileName = flag.String("config", "", "ledisdb config file")
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
cmd.CmdRepair()
|
||||||
|
|
||||||
if len(*fileName) == 0 {
|
|
||||||
println("need ledis config file")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := config.NewConfigWithFile(*fileName)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(cfg.DataDir) == 0 {
|
|
||||||
println("must set data dir")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = store.Repair(cfg); err != nil {
|
|
||||||
println("repair error: ", err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,120 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"github.com/ledisdb/ledisdb/cmd"
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
_ "net/http/pprof"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/ledisdb/ledisdb/config"
|
|
||||||
"github.com/ledisdb/ledisdb/server"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var configFile = flag.String("config", "", "ledisdb config file")
|
|
||||||
var addr = flag.String("addr", "", "ledisdb listen address")
|
|
||||||
var dataDir = flag.String("data_dir", "", "ledisdb base data dir")
|
|
||||||
var dbName = flag.String("db_name", "", "select a db to use, it will overwrite the config's db name")
|
|
||||||
var usePprof = flag.Bool("pprof", false, "enable pprof")
|
|
||||||
var pprofPort = flag.Int("pprof_port", 6060, "pprof http port")
|
|
||||||
var slaveof = flag.String("slaveof", "", "make the server a slave of another instance")
|
|
||||||
var readonly = flag.Bool("readonly", false, "set readonly mode, slave server is always readonly")
|
|
||||||
var rpl = flag.Bool("rpl", false, "enable replication or not, slave server is always enabled")
|
|
||||||
var rplSync = flag.Bool("rpl_sync", false, "enable sync replication or not")
|
|
||||||
var ttlCheck = flag.Int("ttl_check", 0, "TTL check interval")
|
|
||||||
var databases = flag.Int("databases", 0, "ledisdb maximum database number")
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
cmd.CmdServer()
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
var cfg *config.Config
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if len(*configFile) == 0 {
|
|
||||||
println("no config set, using default config")
|
|
||||||
cfg = config.NewConfigDefault()
|
|
||||||
} else {
|
|
||||||
cfg, err = config.NewConfigWithFile(*configFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*addr) > 0 {
|
|
||||||
cfg.Addr = *addr
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*dataDir) > 0 {
|
|
||||||
cfg.DataDir = *dataDir
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*dbName) > 0 {
|
|
||||||
cfg.DBName = *dbName
|
|
||||||
}
|
|
||||||
|
|
||||||
if *databases > 0 {
|
|
||||||
cfg.Databases = *databases
|
|
||||||
}
|
|
||||||
|
|
||||||
// check bool flag, use it.
|
|
||||||
for _, arg := range os.Args {
|
|
||||||
arg := strings.ToLower(arg)
|
|
||||||
switch arg {
|
|
||||||
case "-rpl", "-rpl=true", "-rpl=false":
|
|
||||||
cfg.UseReplication = *rpl
|
|
||||||
case "-readonly", "-readonly=true", "-readonly=false":
|
|
||||||
cfg.Readonly = *readonly
|
|
||||||
case "-rpl_sync", "-rpl_sync=true", "-rpl_sync=false":
|
|
||||||
cfg.Replication.Sync = *rplSync
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(*slaveof) > 0 {
|
|
||||||
cfg.SlaveOf = *slaveof
|
|
||||||
cfg.Readonly = true
|
|
||||||
cfg.UseReplication = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if *ttlCheck > 0 {
|
|
||||||
cfg.TTLCheckInterval = *ttlCheck
|
|
||||||
}
|
|
||||||
|
|
||||||
var app *server.App
|
|
||||||
app, err = server.NewApp(cfg)
|
|
||||||
if err != nil {
|
|
||||||
println(err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sc := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sc,
|
|
||||||
os.Kill,
|
|
||||||
os.Interrupt,
|
|
||||||
syscall.SIGHUP,
|
|
||||||
syscall.SIGINT,
|
|
||||||
syscall.SIGTERM,
|
|
||||||
syscall.SIGQUIT)
|
|
||||||
|
|
||||||
if *usePprof {
|
|
||||||
go func() {
|
|
||||||
log.Println(http.ListenAndServe(fmt.Sprintf(":%d", *pprofPort), nil))
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
go app.Run()
|
|
||||||
|
|
||||||
<-sc
|
|
||||||
|
|
||||||
println("ledis-server is closing")
|
|
||||||
app.Close()
|
|
||||||
println("ledis-server is closed")
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/ledisdb/ledisdb/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cmds = [][]string{
|
||||||
|
{"server", "run ledis server"},
|
||||||
|
{"cli", "run ledis client"},
|
||||||
|
{"repair", "repair ledis storage directory"},
|
||||||
|
{"dump", "create a snapshort of ledis"},
|
||||||
|
{"load", "load data from a snapshort"},
|
||||||
|
{"benchmark", "run the benchmarks with ledis"},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func printSubCmds() {
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
printCmd(cmd[0], cmd[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printCmd(cmd, description string) {
|
||||||
|
fmt.Printf("%s\t- %s\n", cmd, description)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var subCmd string
|
||||||
|
if len(os.Args) == 1 {
|
||||||
|
subCmd = "server"
|
||||||
|
} else {
|
||||||
|
subCmd = os.Args[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
switch subCmd {
|
||||||
|
case "repair":
|
||||||
|
cmd.CmdRepair()
|
||||||
|
case "benchmark":
|
||||||
|
cmd.CmdBenchmark()
|
||||||
|
case "cli":
|
||||||
|
cmd.CmdCli()
|
||||||
|
case "dump":
|
||||||
|
cmd.CmdDump()
|
||||||
|
case "help":
|
||||||
|
printSubCmds()
|
||||||
|
case "server":
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
cmd.CmdServer()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/ledisdb/ledisdb/config"
|
||||||
|
"github.com/ledisdb/ledisdb/ledis"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CmdLoad() {
|
||||||
|
var configPath = flag.String("config", "", "ledisdb config file")
|
||||||
|
var dumpPath = flag.String("dump_file", "", "ledisdb dump file")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if len(*configPath) == 0 {
|
||||||
|
println("need ledis config file")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := config.NewConfigWithFile(*configPath)
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(*dumpPath) == 0 {
|
||||||
|
println("need dump file")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cfg.DataDir) == 0 {
|
||||||
|
println("must set data dir")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ldb, err := ledis.Open(cfg)
|
||||||
|
if err != nil {
|
||||||
|
println("ledis open error ", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = loadDump(cfg, ldb, dumpPath)
|
||||||
|
ldb.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Load OK")
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadDump(cfg *config.Config, ldb *ledis.Ledis, dumpPath *string) error {
|
||||||
|
var err error
|
||||||
|
if err = ldb.FlushAll(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = ldb.LoadDumpFile(*dumpPath)
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/ledisdb/ledisdb/config"
|
||||||
|
"github.com/ledisdb/ledisdb/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CmdRepair() {
|
||||||
|
var fileName = flag.String("config", "", "ledisdb config file")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if len(*fileName) == 0 {
|
||||||
|
println("need ledis config file")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := config.NewConfigWithFile(*fileName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cfg.DataDir) == 0 {
|
||||||
|
println("must set data dir")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = store.Repair(cfg); err != nil {
|
||||||
|
println("repair error: ", err.Error())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/ledisdb/ledisdb/config"
|
||||||
|
"github.com/ledisdb/ledisdb/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
var addr = flag.String("addr", "", "ledisdb listen address")
|
||||||
|
var dataDir = flag.String("data_dir", "", "ledisdb base data dir")
|
||||||
|
var dbName = flag.String("db_name", "", "select a db to use, it will overwrite the config's db name")
|
||||||
|
var usePprof = flag.Bool("pprof", false, "enable pprof")
|
||||||
|
var pprofPort = flag.Int("pprof_port", 6060, "pprof http port")
|
||||||
|
var slaveof = flag.String("slaveof", "", "make the server a slave of another instance")
|
||||||
|
var readonly = flag.Bool("readonly", false, "set readonly mode, slave server is always readonly")
|
||||||
|
var rpl = flag.Bool("rpl", false, "enable replication or not, slave server is always enabled")
|
||||||
|
var rplSync = flag.Bool("rpl_sync", false, "enable sync replication or not")
|
||||||
|
var ttlCheck = flag.Int("ttl_check", 0, "TTL check interval")
|
||||||
|
var databases = flag.Int("databases", 0, "ledisdb maximum database number")
|
||||||
|
|
||||||
|
func CmdServer() {
|
||||||
|
var configFile = flag.String("config", "", "ledisdb config file")
|
||||||
|
|
||||||
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var cfg *config.Config
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if len(*configFile) == 0 {
|
||||||
|
println("no config set, using default config")
|
||||||
|
cfg = config.NewConfigDefault()
|
||||||
|
} else {
|
||||||
|
cfg, err = config.NewConfigWithFile(*configFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(*addr) > 0 {
|
||||||
|
cfg.Addr = *addr
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(*dataDir) > 0 {
|
||||||
|
cfg.DataDir = *dataDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(*dbName) > 0 {
|
||||||
|
cfg.DBName = *dbName
|
||||||
|
}
|
||||||
|
|
||||||
|
if *databases > 0 {
|
||||||
|
cfg.Databases = *databases
|
||||||
|
}
|
||||||
|
|
||||||
|
// check bool flag, use it.
|
||||||
|
for _, arg := range os.Args {
|
||||||
|
arg := strings.ToLower(arg)
|
||||||
|
switch arg {
|
||||||
|
case "-rpl", "-rpl=true", "-rpl=false":
|
||||||
|
cfg.UseReplication = *rpl
|
||||||
|
case "-readonly", "-readonly=true", "-readonly=false":
|
||||||
|
cfg.Readonly = *readonly
|
||||||
|
case "-rpl_sync", "-rpl_sync=true", "-rpl_sync=false":
|
||||||
|
cfg.Replication.Sync = *rplSync
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(*slaveof) > 0 {
|
||||||
|
cfg.SlaveOf = *slaveof
|
||||||
|
cfg.Readonly = true
|
||||||
|
cfg.UseReplication = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if *ttlCheck > 0 {
|
||||||
|
cfg.TTLCheckInterval = *ttlCheck
|
||||||
|
}
|
||||||
|
|
||||||
|
var app *server.App
|
||||||
|
app, err = server.NewApp(cfg)
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sc := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sc,
|
||||||
|
os.Kill,
|
||||||
|
os.Interrupt,
|
||||||
|
syscall.SIGHUP,
|
||||||
|
syscall.SIGINT,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
syscall.SIGQUIT)
|
||||||
|
|
||||||
|
if *usePprof {
|
||||||
|
go func() {
|
||||||
|
log.Println(http.ListenAndServe(fmt.Sprintf(":%d", *pprofPort), nil))
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
go app.Run()
|
||||||
|
|
||||||
|
<-sc
|
||||||
|
|
||||||
|
println("ledis-server is closing")
|
||||||
|
app.Close()
|
||||||
|
println("ledis-server is closed")
|
||||||
|
}
|
Loading…
Reference in New Issue