// benchmark benchmarks the given command with the given parameters // and displays the given test name. func benchmark(testname string, command string, params ...interface{}) { fmt.Printf("===== %s =====\n", testname) c := redis.NewClient(conf) defer c.Close() ch := make(chan struct{}) doneChan := make(chan struct{}) start := time.Now() for i := 0; i < *connections; i++ { go test(c, ch, doneChan, command, params...) } for i := 0; i < *requests; i++ { ch <- struct{}{} } close(ch) for i := 0; i < *connections; i++ { <-doneChan } duration := time.Now().Sub(start) rps := float64(*requests) / duration.Seconds() fmt.Println("Requests per second:", rps) fmt.Printf("Duration: %v\n\n", duration.Seconds()) }
// benchmark benchmarks the given function. func benchmark(data string, handle func(string, *redis.Client, chan struct{})) time.Duration { conf := redis.DefaultConfig() conf.Database = 8 conf.PoolCapacity = *connections c := redis.NewClient(conf) defer c.Close() rep := c.Flushdb() if rep.Err != nil { handleReplyError(rep) os.Exit(1) } ch := make(chan struct{}) start := time.Now() for i := 0; i < *connections; i++ { go handle(data, c, ch) } for i := 0; i < *requests; i++ { ch <- struct{}{} } dur := time.Now().Sub(start) return dur }
func main() { c := redis.NewClient(redisConf()) defer c.Close() h := func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { // TODO return error if these are not set // TODO do we need a mutex here? c.Publish(r.FormValue("channel"), r.FormValue("data")) } if r.Method == "GET" { // spawn a new client since we'll be modifing pubsub behavior c := redis.NewClient(redisConf()) defer c.Close() // TODO allow channel size to be configurable lines := make(chan string) h := func(msg *redis.Message) { switch msg.Type { case redis.MessageMessage: lines <- msg.Payload } } sub, err := c.Subscription(h) if err != nil { panic(err) } defer sub.Close() sub.Subscribe(r.FormValue("channel")) for l := range lines { fmt.Fprintf(w, "%s\n", l) if f, ok := w.(http.Flusher); ok { f.Flush() } } } } http.HandleFunc("/", h) err := http.ListenAndServe(":"+os.Getenv("PORT"), nil) if err != nil { panic(err) } }
func main() { var c *redis.Client conf := redis.DefaultConfig() // Network and address // // Default are "tcp" and "127.0.0.1:6379" so these are commented out. // TCP example: // conf.Network = "tcp" // conf.Address = "127.0.0.1:6379" // Unix example: // conf.Network = "unix" // conf.Address = "/tmp/redis.sock" conf.Database = 8 // Database number conf.Timeout = time.Duration(10) * time.Second // Socket timeout c = redis.NewClient(conf) defer c.Close() //** Blocking calls rep := c.Flushdb() if rep.Err != nil { fmt.Println("redis:", rep.Err) return } //* Strings // It's generally good idea to check for errors like this, // but for the sake of keeping this example short we'll omit these from now on. if rep = c.Set("mykey0", "myval0"); rep.Err != nil { fmt.Println("redis:", rep.Err) return } var err error var s string if rep = c.Get("mykey0_may_not_exist"); rep.Type == redis.ReplyNil { //key not found fmt.Println("key not found ") } else if s, err = rep.Str(); err != nil { fmt.Println("Get error ", err) return } fmt.Println("mykey0:", s) myhash := map[string]string{ "mykey1": "myval1", "mykey2": "myval2", "mykey3": "myval3", } // Alternatively: // c.Mset("mykey1", "myval1", "mykey2", "myval2", "mykey3", "myval3") c.Mset(myhash) ls, err := c.Mget("mykey1", "mykey2", "mykey3").List() if err != nil { fmt.Println(err) return } fmt.Println("mykeys values:", ls) //* List handling mylist := []string{"foo", "bar", "qux"} // Alternativaly: // c.Rpush("mylist", "foo", "bar", "qux") c.Rpush("mylist", mylist) mylist, err = c.Lrange("mylist_may_not_exist", 0, -1).List() if err != nil { fmt.Println(err) return } fmt.Println("mylist:", mylist) //* Hash handling // Alternatively: // c.Hmset("myhash", ""mykey1", "myval1", "mykey2", "myval2", "mykey3", "myval3") c.Hmset("myhash", myhash) myhash, err = c.Hgetall("myhash").Hash() if err != nil { fmt.Println(err) return } fmt.Println("myhash:", myhash) //* Multicalls rep = c.MultiCall(func(mc *redis.MultiCall) { mc.Set("multikey", "multival") mc.Get("multikey") }) // Multicall reply is guaranteed to have the same number of sub-replies as calls, // if it succeeds. They can be accessed through Reply.Elems. if rep.Err != nil { fmt.Println(rep.Err) return } s, err = rep.Elems[1].Str() if err != nil { fmt.Println(err) return } fmt.Println("multikey:", s) //* Transactions rep = c.Transaction(func(mc *redis.MultiCall) { mc.Set("trankey", "tranval") mc.Get("trankey") }) if rep.Err != nil { fmt.Println(rep.Err) return } s, err = rep.Elems[1].Str() if err != nil { fmt.Println(err) return } fmt.Println("trankey:", s) //* Complex transactions // Atomic INCR replacement with transactions myIncr := func(key string) *redis.Reply { return c.MultiCall(func(mc *redis.MultiCall) { var curval int mc.Watch(key) mc.Get(key) rep := mc.Flush() if rep.Err != nil { return } s, err := rep.Elems[1].Str() if err == nil { curval, err = strconv.Atoi(s) } nextval := curval + 1 mc.Multi() mc.Set(key, nextval) mc.Exec() }) } myIncr("ctrankey") myIncr("ctrankey") myIncr("ctrankey") s, err = c.Get("ctrankey").Str() if err != nil { fmt.Println(err) return } fmt.Println("ctrankey:", s) //** Asynchronous calls c.Set("asynckey", "asyncval") fut := c.AsyncGet("asynckey") // do something here // block until reply is available s, err = fut.Reply().Str() if err != nil { fmt.Println(err) return } fmt.Println("asynckey:", s) //* Pub/sub msgHdlr := func(msg *redis.Message) { switch msg.Type { case redis.MessageMessage: fmt.Printf("Received message \"%s\" from channel \"%s\".\n", msg.Payload, msg.Channel) case redis.MessagePmessage: fmt.Printf("Received pattern message \"%s\" from channel \"%s\" with pattern "+ "\"%s\".\n", msg.Payload, msg.Channel, msg.Pattern) default: fmt.Println("Received other message:", msg) } } sub, err_ := c.Subscription(msgHdlr) if err_ != nil { fmt.Printf("Failed to subscribe: '%s'!\n", err_) return } defer sub.Close() sub.Subscribe("chan1", "chan2") sub.Psubscribe("chan*") c.Publish("chan1", "foo") sub.Unsubscribe("chan1") c.Publish("chan2", "bar") // give some time for the message handler to receive the messages time.Sleep(time.Second) }
func NewAuditor(conf redis.Config) *Auditor { return &Auditor{ client: redis.NewClient(conf), } }
func flushdb() *redis.Error { c := redis.NewClient(conf) defer c.Close() rep := c.Flushdb() return rep.Err }
func main() { // initialize conf := redis.DefaultConfig() client := redis.NewClient(conf) fmt.Println(conf) fmt.Println(client) // set & get setRep := client.Set("foo", "bar") if setRep.Err != nil { panic(setRep.Err) } fmt.Println(setRep) getRep := client.Get("foo") if getRep.Err != nil { panic(getRep.Err) } getStr, _ := getRep.Str() fmt.Println(getRep) fmt.Println(getStr) // variadic calls client.Set("foo1", "bar1") client.Set("foo2", "bar2") client.Set("foo3", "bar3") mgetRep := client.Mget("foo1", "foo2", "foo3") fmt.Println(mgetRep) // multi calls mcRep := client.MultiCall(func(mc *redis.MultiCall) { mc.Set("k1", "v1") mc.Get("k1") }) if mcRep.Err != nil { panic(mcRep.Err) } mcVal, _ := mcRep.Elems[1].Str() fmt.Println(mcVal) // transactional calls tRep := client.Transaction(func(mc *redis.MultiCall) { mc.Set("k2", "v2") mc.Get("k2") }) if tRep.Err != nil { panic(tRep.Err) } tStr, _ := tRep.Elems[1].Str() fmt.Println(tStr) // pubsub msgHdlr := func(msg *redis.Message) { fmt.Println(msg) } sub, subErr := client.Subscription(msgHdlr) if subErr != nil { panic(subErr) } defer sub.Close() sub.Subscribe("chan1", "chan2") sub.Psubscribe("chan*") client.Publish("chan1", "foo") sub.Unsubscribe("chan1") client.Publish("chan2", "bar") time.Sleep(time.Second) }