Пример #1
0
func makeConn(addr, pwd string) (conn *redisConn, err error) {
	log.Info("makeConn|%v|%v", addr, pwd)
	conn = nil
	const dataTimeout = 5 * time.Second
	const connTimeout = 2 * time.Second
	var c redis.Conn
	if c, err = redis.DialTimeout("tcp", addr, connTimeout, dataTimeout, dataTimeout); err != nil {
		log.Error("makeConn|DialTimeout|%v", err)
		return
	}
	if pwd != "" {
		if _, err = c.Do("AUTH", pwd); err != nil {
			log.Error("makeConn|auth|%v", err)
			c.Close()
			return
		}
	}
	if _, err = c.Do("get", "__test"); err != nil {
		log.Error("makeConn|get|%v", err)
		c.Close()
		return
	}
	log.Info("makeConn|ok|%v", addr)
	var now = time.Now().Unix()
	conn = &redisConn{c, addr, seed, now + pingInterval, now}
	seed++
	return
}
Пример #2
0
func (w *Worker) start() {
	workWait.Add(1)
	defer func() {
		for _, db := range w.dbmap {
			db.Close()
		}
		if w.getbuff != 0 {
			C.free(unsafe.Pointer(w.getbuff))
		}
		log.Info("server|close|work|%d", w.id)
		workWait.Done()
	}()
	for req := range workChan {
		switch req := req.(type) {
		case bdbSetReq:
			if req.sec == 0 {
				w.bdbSet(&req)
			} else {
				w.bdbSetEx(&req)
			}
		case bdbGetReq:
			w.bdbGet(&req)
		case bdbIncrByReq:
			w.bdbIncrBy(&req)
		}
	}
}
Пример #3
0
func (pool *Pool) processSlaveWrite(conn *redisConn, err string) {
	log.Info("receive|slavewrite")
	// 主从切换了
	if strings.HasSuffix(err, ",unknown") {
		conn.pingTime = time.Now().Add(2 * time.Second).Unix()
		pool.connCh <- conn
	} else {
		params := strings.SplitN(err, ",", 2)
		if len(params) != 2 {
			log.Error("process|slavewrite|format_error|%s", err)
		} else {
			var newip = params[1]
			log.Info("receive|new_master|%v", newip)
			pool.newMasterCh <- newip
		}
		pool.badCh <- conn
	}
}
Пример #4
0
func (pool *Pool) checkEvent() {
	var timer *time.Timer
	for {
		if timer == nil {
			// 第一次等5秒
			timer = time.NewTimer(5 * time.Second)
		} else {
			// 如果触发事件后就需要立即处理
			// 但是为了防止cleanConn触发的大量badCh事件
			// 所以先等待50毫秒
			timer.Stop()
			timer = time.NewTimer(50 * time.Millisecond)
		}
		select {
		case newMaster := <-pool.newMasterCh:
			log.Info("checkEvent|newMasterCh|%v", newMaster)
			var found = false
			for i := 0; i < len(pool.addrs); i++ {
				if pool.addrs[i] == newMaster {
					log.Info("checkNewMaster|found")
					pool.addrs[0], pool.addrs[i] = pool.addrs[i], pool.addrs[0]
					pool.cleanConn()
					found = true
					break
				}
			}
			if !found {
				log.Error("checkEvent|newMasterCh|not_found|%v", newMaster)
			}
		case newAddr := <-pool.addrCh:
			log.Info("checkEvent|addrCh|%v", newAddr)
			pool.cleanConn()
			pool.poolAddr = newAddr
		case bad := <-pool.badCh:
			log.Info("checkEvent|badCh|%v|%v", bad.id, bad.addr)
			pool.total--
			bad.conn.Close()
		case <-timer.C:
			return
		}
	}
}
Пример #5
0
func (pool *Pool) cleanConn() {
	log.Info("cleanConn")
	for pool.total > 0 {
		var conn *redisConn
		select {
		case conn = <-pool.connCh:
		case conn = <-pool.badCh:
		}
		conn.conn.Close()
		pool.total--
	}
	log.Debug("cleanConn|ok")
}
Пример #6
0
func main() {
	flag.Parse()
	gomax := int(float64(runtime.NumCPU()) * 1.5)
	runtime.GOMAXPROCS(gomax)

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	log.InitFromFile(*logconf)
	log.Info("version:%v", util.GetVersion())
	log.Info("start...")

	Init()

	go myweb.Start(config.SConfig.Http, config.SConfig.Https)
	log.Info("Welcome to mysvrs")

	<-signalChan
	log.Info("bye")
	os.Exit(0)

}
Пример #7
0
func (pool *Pool) processWorker(conn *redisConn, reqs []*redisReq) {
	var err = processRequest(conn, reqs)
	if err != nil {
		log.Info("process|processRequest|%v", err)
		if strings.HasPrefix(err.Error(), "ERR slavewrite,") {
			pool.processSlaveWrite(conn, err.Error())
		} else {
			pool.badCh <- conn
		}
	} else {
		conn.pingTime = time.Now().Add(pingInterval).Unix()
		pool.connCh <- conn
	}
	reqsPool.Put(reqs)
}
Пример #8
0
func (pool *Pool) testConn() {
	// testConn每次只检查一个连接
	var conn *redisConn
	select {
	case conn = <-pool.connCh:
	default:
		// 没有空闲的连接
		// 表示现在比较忙
		// 暂时就不检查了
		return
	}

	var masterAddr = pool.addrs[0]
	if conn.addr != masterAddr {
		if newconn, err := makeConn(masterAddr, pool.pwd); err != nil {
			log.Error("bkWorker|makeConn|%v", err)
		} else {
			// 主服务器已经能够连上了
			conn.conn.Close()
			conn = newconn
		}
	}
	if time.Now().Unix() > conn.pingTime {
		// 超过pingInterval,则ping一下连接
		if _, err := conn.conn.Do("set", "__ping", "1"); err != nil {
			if strings.HasPrefix(err.Error(), "ERR slavewrite,") {
				pool.processSlaveWrite(conn, err.Error())
			} else {
				log.Info("process|ping|%v", err)
				pool.badCh <- conn
			}
		} else {
			log.Debug("bgWorker|ping")
			pool.connCh <- conn
		}
	} else {
		pool.connCh <- conn
	}
	return
}
Пример #9
0
func Start(config BdbConfig) *DbEnv {
	args := make([]string, 0, 20)
	if config.AckAll && config.RepMgr {
		args = append(args, "-a")
	}
	if config.Bulk {
		args = append(args, "-b")
	}
	if config.Master {
		args = append(args, "-M")
	} else if !config.RepMgr {
		args = append(args, "-C")
	}

	if config.HomeDir == "" {
		log.Fatal("bdb|homedir_missing")
	}
	args = append(args, "-h", config.HomeDir)
	_, err := os.Stat(config.HomeDir)
	if err != nil && os.IsNotExist(err) {
		os.Mkdir(config.HomeDir, os.ModePerm)
	}
	if config.LocalAddr == "" {
		log.Fatal("bdb|localaddr_missing")
	}
	if config.RepMgr && config.Master {
		args = append(args, "-L", config.LocalAddr)
	} else {
		args = append(args, "-l", config.LocalAddr)
	}

	if config.DisableElection {
		args = append(args, "-p", "0")
	} else if config.Priority != 0 {
		args = append(args, "-p", strconv.FormatInt(int64(config.Priority), 10))
	}

	if config.RepMgr && config.RemotePeer != "" {
		if len(config.RemoteAddr) != 0 {
			log.Fatal("bdb|conflict_RemoteAddr_RemotePeer")
		}
		args = append(args, "-R", config.RemotePeer)
	} else {
		for _, remote := range config.RemoteAddr {
			args = append(args, "-r", remote)
		}
	}

	if config.Verbose {
		args = append(args, "-v")
	}

	dbenv := new(DbEnv)
	dbenv.waitStop.Add(1)
	dbenv.waitExit.Add(1)
	dbenv.waitReady.Add(1)
	go func() {
		argv := make([]*C.char, len(args)+1)
		for i, arg := range args {
			argv[i+1] = C.CString(arg)
		}
		argv[0] = C.CString("bdbd")

		if config.RepMgr {
			log.Info("start_repmgr|%v", args)
			C.start_mgr(C.int(len(argv)), &argv[0], C.int(config.Flush), unsafe.Pointer(dbenv))
		} else {
			log.Info("start_base|%v", args)
			C.start_base(C.int(len(argv)), &argv[0], C.int(config.Flush), unsafe.Pointer(dbenv))
		}

		for _, arg := range argv {
			C.free(unsafe.Pointer(arg))
		}

		dbenv.waitExit.Done()
	}()
	dbenv.waitReady.Wait()
	return dbenv
}
Пример #10
0
//export Info
func Info(msg *C.char) {
	log.Info(C.GoString(msg))
}
Пример #11
0
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU() * 4)

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	// master
	//go run main.go -h db1 -M -l 127.0.0.1:2345 -r 127.0.0.1:2346
	// slave
	//go run main.go -h db2 -C -l 127.0.0.1:2346 -r 127.0.0.1:2345

	configFile := "bdbd.conf"
	if len(os.Args) > 1 {
		configFile = os.Args[1]
	}
	configstr, err := ioutil.ReadFile(configFile)
	if err != nil {
		log.Println("ERROR: read config file failed:", err)
		os.Exit(1)
	}
	var config struct {
		Bdb    bdb.BdbConfig        `toml:"bdb"`
		Logger []mylog.LoggerDefine `toml:"logger"`
		Server struct {
			Listen string
		} `toml:"server"`
	}
	config.Bdb.Flush = 1
	_, err = toml.Decode(string(configstr), &config)
	if err != nil {
		log.Println("ERROR: decode config failed:", err)
		os.Exit(1)
	}

	mylog.Init(config.Logger)

	mylog.Info("bdb|starting")
	dbenv := bdb.Start(config.Bdb)
	mylog.Info("bdb|started")

	/*
		db, err := dbenv.GetDb("test")
		if err != nil {
			mylog.Fatal("dberr:%s", err.Error())
		}
		for i := 0; i < 1000000; i++ {
			if i%1000 == 0 {
				mylog.Info("%d", i)
			}
			k := fmt.Sprintf("k_%v", i)
			db.Set([]byte(k), []byte(k))
		}
		db.Close()
		dbenv.Exit()
		mylog.Fatal("end")
	*/

	go func() {
		addr, err := net.ResolveTCPAddr("tcp", config.Server.Listen)
		if err != nil {
			mylog.Fatal("ResolveTCPAddr|%s", err.Error())
		}
		listener, err := net.ListenTCP("tcp", addr)
		if err != nil {
			mylog.Fatal("Server|ListenTCP|%s", err.Error())
		}
		for {
			client, err := listener.AcceptTCP()
			if err != nil {
				mylog.Error("Server|%s", err.Error())
			}
			client.SetKeepAlive(true)
			conn := server.NewConn(client, dbenv)
			go conn.Start()
		}
	}()

	server.Start(dbenv)
	mylog.Info("start")
	<-signalChan
	server.Exit()
	dbenv.Exit()
	mylog.Info("bye")
}