当前比较好用的redis golang v5的redis客户端有哪些

在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context
这是log中错误信息
我用了go-redis这个库
package cache
"/go-redis/redis"
*redis.Client
Password string
func Init(addr, password string, dbNum int) {
Client = redis.NewClient(&redis.Options{
Password: password,
_, err := Client.Ping().Result()
if err != nil {
panic(err.Error())
Addr = addr
Password = password
DBNum = dbNum
func NewClient() *redis.Client {
client := redis.NewClient(&redis.Options{
Password: Password,
_, err := client.Ping().Result()
if err != nil {
log.Error("create subscription client failed " + err.Error())
return nil
return client
Client是平常的操作Client订阅的Client是用的NewClient()的
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
pub 和sub 应该使用不同的client文档里面说的有
The commands that are allowed in the context of a subscribed client are SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, PING and QUIT.
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:随笔 - 168&
trackbacks - 0
282930313469101112131415161718202125262728293012345678
专注即时通讯及网游服务端编程
------------------------------------
本博收藏大部分文章为转载,并在文章开头给出了原文出处,如有再转,敬请保留相关信息,这是大家对原创作者劳动成果的自觉尊重!!如为您带来不便,请于本博下留言,谢谢配合。
Awesome中文聚合
Stable APIs for Golang
way to explore
积分与排名
阅读排行榜
/wolfred7464/p/4670864.htmlredis的client有好多好多,go语言的client在redis官方有两个推荐,radix和redigo。选择哪一个好呢?确实很纠结,后来掷硬币决定选择redigo了。redis、go、redigo的安装就不需要提了,不能强行增加篇幅。redigo使用起来很人性化,api设计的符合直觉,我对redis了解较少,使用过程中基本没有遇到障碍。redigo的使用入门可以去查godoc:接下来就是毫无技术含量的贴代码了:连接redis我一般是这样写的:c,&err&:=&redis.Dial("tcp",&"127.0.0.1:6379")if&err&!=&nil&{&&&&fmt.Println(err)&&&&return}defer&c.Close()执行命令使用Do函数,跟在redis-cli敲命令的感觉差不多的:v,&err&:=&c.Do("SET",&"name",&"red")if&err&!=&nil&{&&&&fmt.Println(err)&&&&return}fmt.Println(v)v,&err&=&redis.String(c.Do("GET",&"name"))if&err&!=&nil&{&&&&fmt.Println(err)&&&&return}fmt.Println(v)列表也是一样:c.Do("lpush",&"redlist",&"qqq")c.Do("lpush",&"redlist",&"www")c.Do("lpush",&"redlist",&"eee")读取列表可以for循环遍历,也可以使用redis.Scan函数:values,&_&:=&redis.Values(c.Do("lrange",&"redlist",&"0",&"100"))for&_,&v&:=&range&values&{&&&&fmt.Println(string(v.([]byte)))}//&或者var&v1&stringredis.Scan(values,&&v1)fmt.Println(v1)管道:c.Send("SET",&"name",&"red")c.Send("GET",&"name")c.Flush()c.Receive()c.Receive()发布订阅:func&subscribe()&{&&&&c,&err&:=&redis.Dial("tcp",&"127.0.0.1:6379")&&&&if&err&!=&nil&{&&&&&&&&fmt.Println(err)&&&&&&&&return&&&&}&&&&defer&c.Close()&&&&psc&:=&redis.PubSubConn{c}&&&&psc.Subscribe("redChatRoom")&&&&for&{&&&&&&&&switch&v&:=&psc.Receive().(type)&{&&&&&&&&case&redis.Message:&&&&&&&&&&&&fmt.Printf("%s:&message:&%s\n",&v.Channel,&v.Data)&&&&&&&&case&redis.Subscription:&&&&&&&&&&&&fmt.Printf("%s:&%s&%d\n",&v.Channel,&v.Kind,&v.Count)&&&&&&&&case&error:&&&&&&&&&&&&fmt.Println(v)&&&&&&&&&&&&return&&&&&&&&}&&&&}}go&subscribe()go&subscribe()go&subscribe()go&subscribe()go&subscribe()c,&err&:=&redis.Dial("tcp",&"127.0.0.1:6379")if&err&!=&nil&{&&&&fmt.Println(err)&&&&return}defer&c.Close()for&{&&&&var&s&string&&&&fmt.Scanln(&s)&&&&_,&err&:=&c.Do("PUBLISH",&"redChatRoom",&s)&&&&if&err&!=&nil&{&&&&&&&&fmt.Println("pub&err:&",&err)&&&&&&&&return&&&&}}在应对高并发访问时,结合codis使用redis的连接池。开发语言为golang,使用的是一个在github上开源的golang写的连接池
为了更深入了解golang连接池的实现,自已又重写了一遍连接池。以学习连接服的具体实现逻辑,并优化了生成一个redis连接的负载均衡问题(多个服务地址循环拿取)
也特别感谢同事的帮助
将程序记录到此处 &一来备忘 二来记录自己的成长
程序引用开源包如下
&/alecthomas/log4go&
&/garyburd/redigo/redis&
&/samuel/go-zookeeper/zk&
程序代码 :godis.go
package godis
&container/list&
&encoding/json&
&/alecthomas/log4go&
&/garyburd/redigo/redis&
&/samuel/go-zookeeper/zk&
//连接zk默认过期时间
DEFAULT_ZK_CONNECT_TIMEOUT = 100
//默认最大空间连接数
DEFAULT_MAX_IDLE = 10
//默认最大连接数
DEFAULT_MAX_ACTIVE = 100
type proxyInfo struct {
string `json:&addr&`
State string `json:&state&`
type idleConn struct {
c redis.Conn
t time.Time
type GodisPool struct {
//zk的接点
ZkDir string
//测试方法
TestOnBorrow func(c redis.Conn, t time.Time) error
//zk服务器连接地址
ZkServerList []string
//最大空闲连接
MaxIdle int
//最大连接数
MaxActive int
//超时时间
IdleTimeout time.Duration
//redis服务的连接池,zk接点数据里的addr,只存在线(online)的addr
//pools []redis.Conn
pools []string
ZkConnTimeout time.Duration
//zk连接的实例
zkC zk.Conn
//请求等待
//空闲连接池
idle list.List
//当前连接数
sync.Mutex
*sync.Cond
nextIdx int
nowFunc = time.Now
//当前zk的列表(包括在线和非在线的),用于新服务发现后监听新接点的数据变化,
zkMap = make(map[string]string)
//日志开关
godisLogHandle = false
//初始化方法
func (gp *GodisPool) InitPool() {
if gp.MaxIdle &= 0 {
gp.MaxIdle = DEFAULT_MAX_IDLE
if gp.MaxActive &= 0 {
gp.MaxActive = DEFAULT_MAX_ACTIVE
gp.initZK()
//设置连接池
rsE := gp.resetPools()
if rsE != nil {
fmt.Println(&set pools err:&, rsE.Error())
//启用接点监听,动态更新连接池
go gp.poolWatcher()
//初始化zookeeper
func (gp *GodisPool) initZK() {
zkConn, _, err := zk.Connect(gp.ZkServerList, gp.ZkConnTimeout)
if err != nil {
if godisLogHandle {
log4go.Error(&Failed to connect to zookeeper: %+v&, err)
log4go.Error(&after 100 millisecond reconnect to zk...&)
gp.zkC = *zkConn
//重设连接池
* 获取当前的zk接点,将在线的服务(State为online)创建redis连接
* 放到连接池
* 对于新加进的zk接点设置wather,监听此接点的数据变化
func (gp *GodisPool) resetPools() error {
gp.pools = []string{}
//定义临时map
tmpMap := make(map[string]string)
for tk, tv := range zkMap {
tmpMap[tk] = tv
proxys, _, err := gp.zkC.Children(gp.ZkDir)
if err != nil {
fmt.Println(&connect to zookeeper get children err:&, err)
return err
//var _conn redis.Conn
//var _err error
for _, child := range proxys {
connData, _, err := gp.zkC.Get(gp.ZkDir + &/& + child)
if err != nil {
var p proxyInfo
Uerr := json.Unmarshal(connData, &p)
if Uerr != nil {
fmt.Println(Uerr.Error())
/*_conn, _err = redis.Dial(&tcp&, p.Addr)
if _err != nil {
log4go.Error(&Create redis connection err: %s&, _err.Error())
if p.State == &online& {
gp.pools = append(gp.pools, p.Addr)
_, gRs := tmpMap[child]
//a new node
zkMap[child] = p.Addr
go gp.childWatcher(child)
delete(tmpMap, child)
//删除zkmap里无用的接点
for tk, _ := range tmpMap {
delete(zkMap, tk)
(&new pool len-----&&, len(gp.pools))
(&zkmap------&, zkMap)
return nil
//zk接点监听,在监听到子接点的数量变化后,更新连接池
func (gp *GodisPool) poolWatcher() {
(&start to listen children node change ...&)
_, _, evtC, err := gp.zkC.ChildrenW(gp.ZkDir)
if err != nil {
log4go.Error(&watch zkNode %s err: %s&, gp.ZkDir, err.Error())
evt := &-evtC
if evt.Type == zk.EventSession {
if evt.State == zk.StateConnected {
if evt.State == zk.StateExpired {
gp.zkC.Close()
(&Zookeeper session expired, reconnecting...&)
gp.initZK()
switch evt.Type {
case zk.EventNodeChildrenChanged, zk.EventNodeDataChanged:
(&zk children node change reset pools....&)
time.Sleep(100 * time.Millisecond)
gp.resetPools()
//监听子接点的数据变化,
// 子接点服务的状态变化后(比如某个codis下线,状态由online改为offline),更新连接池
func (gp *GodisPool) childWatcher(childPath string) {
_, _, evtC, err := gp.zkC.GetW(gp.ZkDir + &/& + childPath)
//在接点删除时,会报此错误
if err != nil {
log4go.Error(&wath zkChildNode err: &, err.Error())
evt := &-evtC
switch evt.Type {
case zk.EventNodeDataChanged:
gp.resetPools()
case zk.EventNodeDeleted:
delete(zkMap, childPath)
//overWrite get method
func (gp *GodisPool) Get() redis.Conn {
c, err := gp.get()
if err != nil {
return errorConnection{err}
return &pooledConnection{p: gp, c: c}
*在请求连接池里拿一个连接
* 超时判断,将超时的连接删除
* 在idle里拿连接资源,如果没有空间资源 , 从redis连接池拿一条(此处加平均原则),使用后放入idle
func (gp *GodisPool) get() (redis.Conn, error) {
gp.mutex.Lock()
if timeout := gp.IdleT timeout & 0 {
for i, n := 0, gp.idle.Len(); i & i++ {
e := gp.idle.Back()
if e == nil {
ic := e.Value.(idleConn)
if ic.t.Add(timeout).After(nowFunc()) {
gp.idle.Remove(e)
gp.release()
gp.mutex.Unlock()
ic.c.Close()
gp.mutex.Lock()
(&active=-----------------&, gp.active)
(&idle=----------------&&, gp.idle.Len())
//// Get idle connection.
for i, n := 0, gp.idle.Len(); i & i++ {
e := gp.idle.Front()
if e == nil {
ic := e.Value.(idleConn)
gp.idle.Remove(e)
test := gp.TestOnBorrow
gp.mutex.Unlock()
if test == nil || test(ic.c, ic.t) == nil {
fmt.Println(&---get----from----idle---&)
return ic.c, nil
ic.c.Close()
gp.mutex.Lock()
gp.release()
// Dial new connection if under limit.
if gp.MaxActive == 0 || gp.active & gp.MaxActive {
if len(gp.pools) == 0 {
rsE := gp.resetPools()
if rsE != nil {
gp.mutex.Unlock()
return nil, rsE
gp.nextIdx += 1
if gp.nextIdx &= len(gp.pools) {
gp.nextIdx = 0
if len(gp.pools) == 0 {
gp.mutex.Unlock()
err := errors.New(&Proxy list empty&)
log4go.Error(err)
return nil, err
fmt.Println(&---get----from----new---&)
c := gp.pools[gp.nextIdx]
gp.active += 1
_conn, _err := redis.Dial(&tcp&, c)
gp.mutex.Unlock()
if _err != nil {
log4go.Error(&Create redis connection err: %s&, _err.Error())
return nil, _err
test := gp.TestOnBorrow
if test == nil || test(_conn, nowFunc()) == nil {
return _conn, nil
_conn = nil
gp.mutex.Lock()
gp.release()
gp.mutex.Unlock()
return _conn, errors.New(&Create redis connection err&)
if !gp.Wait {
gp.mutex.Unlock()
return nil, errors.New(&connect pool exhausted&)
if gp.cond == nil {
gp.cond = sync.NewCond(&gp.mutex)
gp.cond.Wait()
//释放一个当前存活数
func (gp *GodisPool) release() {
gp.active -= 1
if gp.cond != nil {
gp.cond.Signal()
//将一个连接放回idle
//如果空闲数已到设置的值,将此连接关闭
func (gp *GodisPool) put(c redis.Conn) error {
err := c.Err()
gp.mutex.Lock()
if err == nil {
if gp.idle.Len() & gp.MaxIdle {
gp.idle.PushFront(idleConn{c: c, t: nowFunc()})
fmt.Println(&add-to-idle=----------------&&, gp.idle.Len())
if gp.cond != nil {
gp.cond.Signal()
gp.release()
gp.mutex.Unlock()
return nil
fmt.Println(&----errr===&, err)
gp.release()
gp.mutex.Unlock()
return c.Close()
//Get方法返回的结构体重写
type pooledConnection struct {
*GodisPool
redis.Conn
func (pc *pooledConnection) Close() error {
pc.p.put(c)
return nil
func (pc *pooledConnection) Err() error {
return pc.c.Err()
func (pc *pooledConnection) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
ci := LookupCommandInfo(commandName)
pc.state = (pc.state | ci.Set) &^ ci.Clear
return pc.c.Do(commandName, args...)
func (pc *pooledConnection) Send(commandName string, args ...interface{}) error {
ci := LookupCommandInfo(commandName)
pc.state = (pc.state | ci.Set) &^ ci.Clear
return pc.c.Send(commandName, args...)
func (pc *pooledConnection) Flush() error {
return pc.c.Flush()
func (pc *pooledConnection) Receive() (reply interface{}, err error) {
return pc.c.Receive()
WatchState = 1 && iota
MultiState
SubscribeState
MonitorState
type CommandInfo struct {
Set, Clear int
var commandInfos = map[string]CommandInfo{
{Set: WatchState},
&UNWATCH&:
{Clear: WatchState},
{Set: MultiState},
{Clear: WatchState | MultiState},
&DISCARD&:
{Clear: WatchState | MultiState},
&PSUBSCRIBE&: {Set: SubscribeState},
&SUBSCRIBE&:
{Set: SubscribeState},
&MONITOR&:
{Set: MonitorState},
//初始化配置
func init() {
for n, ci := range commandInfos {
commandInfos[strings.ToLower(n)] = ci
log4go.LoadConfiguration(&log4g.xml&)
godisLogHandle = true
func LookupCommandInfo(commandName string) CommandInfo {
if ci, ok := commandInfos[commandName]; ok {
return commandInfos[strings.ToUpper(commandName)]
type errorConnection struct{ err error }
func (ec errorConnection) Do(string, ...interface{}) (interface{}, error) { return nil, ec.err }
func (ec errorConnection) Send(string, ...interface{}) error
{ return ec.err }
func (ec errorConnection) Err() error
{ return ec.err }
func (ec errorConnection) Close() error
{ return ec.err }
func (ec errorConnection) Flush() error
{ return ec.err }
func (ec errorConnection) Receive() (interface{}, error)
{ return nil, ec.err }
测试程序代码:godis-test.go
package main
&/garyburd/redigo/redis&
&gotest/godis&
Godispool *godis.GodisPool
func main() {
Godispool = &godis.GodisPool{
MaxActive:
ZkServerList:
[]string{&127.0.0.1:2181&}, //10.20.30.91
&/serverlist&,
IdleTimeout:
(time.Duration(3) * time.Second),
ZkConnTimeout: 3 * time.Second,
TestOnBorrow: func(c redis.Conn, t time.Time) error {
if _, err := c.Do(&PING&); err != nil {
return err
return nil
Godispool.InitPool()
gConn := Godispool.Get()
_, sErr := gConn.Do(&set&, &aaa&, &aaaaaaaaa&)
if sErr != nil {
fmt.Println(&set err -: &, sErr.Error())
rs, err := redis.String(gConn.Do(&get&, &aaa&))
if err != nil {
fmt.Println(&get err:&, err.Error())
fmt.Println(&rs--&, rs)
//time.Sleep(time.Second)
//CConn := Godispool.Get()
//fmt.Println(&----222-----&)
//rs2, err2 := redis.String(gConn.Do(&get&, &aaa&))
//if err2 != nil {
// fmt.Println(&get err:&, err.Error())
//fmt.Println(&rs----------------------&, rs2)
//defer CConn.Close()
defer gConn.Close()
for i := 0; i & 50; i++ {
go testg()
//time.Sleep(500 * time.Millisecond)
time.Sleep(1000 * time.Second)
func testg() {
gConn := Godispool.Get()
defer gConn.Close()
rs, err := redis.String(gConn.Do(&get&, &aaa&))
if err != nil {
fmt.Println(&get err:&, err.Error())
fmt.Println(&rs----------------------&, rs)
time.Sleep(time.Second)
本文已收录于以下专栏:
相关文章推荐
之前一篇文章介绍过使用redigo连接redis数据库处理,在使用中发现如果初始化一条链接连接redis做相关操作,使用中发现当两个程序交替使用redis时,先前建立的链接会断掉,只能每次操作的时候重...
在golang的项目中,若要频繁的用redis()
生命不止,继续 go go go !!!以前介绍过golang中如何使用sqlite3:
《Go实战–go语言操作sqlite数据库(The way to go)》今天跟大家分享的是如何在golan...
golang的”database/sql”是操作数据库时常用的包,这个包定义了一些sql操作的接口,具体的实现还需要不同数据库的实现,mysql比较优秀的一个驱动是:/go-sql...
golang内部自带了连接池功能,刚开始接触golang的时候不了解这个,还自己搞了一个 sql.Open的对象管理池,真的非常囧啊。
sql.Open函数实际上是返回一个连接池对象,不是单个连接。...
安装 goprotobuf
1.从 /google/protobuf/releases 获取 Protobuf 编译器 protoc(可下载到 Wi...
golang本身没有提供连接mysql的驱动,但是定义了标准接口供第三方开发驱动。这里连接mysql可以使用第三方库,第三方库推荐使用/Go-SQL-Driver/...
原文出处:个人博客地址:http://www.damonyi.cc/?p=11
      之前项目中需要写个Python 版本的Agent,里面用到了Rabbitmq,中间遇到了好多坑啊,最主...
1.为什么使用信道(channel)而不使用TCP连接发送AMQP命令?
对操作系统来说频繁的建立和销毁TCP连接开销非常昂贵,而操作系统每秒建立的连接是有上限的,性能瓶颈不可避免,而只建立一条TCP...
在上一篇moonmq的介绍中(这里),我仅仅简短的罗列了一些moonmq的设计想法,但是对于如何使用并没有详细说明,公司同事无法很好的使用。
对于moonmq的使用,其实很简单,样例代码在这里,...
他的最新文章
讲师:姜飞俊
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)自由、创新、研究、探索
Linux/Windows Mono/DotNet [ Open Source .NET Development/ 使用开源工具进行DotNet软件开发]锐意进取,志存高远.成就梦想,只争朝夕.从你开始,创新世界.【That I exist is a perpetual supprise which is life. Focus on eCommerce】
Redis可以缓存数据,这使得操作数据可以达到一个较快的速度,在一些需要数据较快存储的场合,例如微博,redis发挥着不可替代的作用。在redis的官网,golang驱动有几个,忽然来了兴致,那个才是redis最佳的Go语言驱动?
这些驱动都处于开发的前期,还没有发行正式版,有些已经很久没更新了。从更新日期来看,Gary Burd的和gosexy的最近有更新,而且从他们的README文件来看,他们对redis的支持还不错。很有可能,他们两者会有1个胜出。但到底谁才是最佳的,这个现在还是不能判断。在gosexy的redis源码库中的有个文件,里面就是一些对各个redis的Go驱动的一些简单的性能测试。简单看了一下,里面的代码就是调用他们各自包中的函数来达到测试的功能。大家不妨看一下。这里就通过这个测试,来简单判断一下谁是最佳。
首先,安装各个Go的驱动:
go /alphazero/Go-Redis
go /simonz05/godis
go /garyburd/redigo
go /gosexy/redis
go get cgl.tideland.biz/redis
注意:tcgl原先托管在google,不过现在它现在自己组建源码库了,gosexy的redis的的tcgl_redis_test.go就import了google的版本,不过现在要修改了。也就是注释掉/p/tcgl/redis,添加&cgl.tideland.biz/redis,这样我们才能进行下一步动作。
在一个终端打开redis:
redis-server
我们要进入_benchmarks这个文件夹,里面的README.md有进行性能测试的步骤,这里要进行的性能测试的操作有Ping, Set, Get, Incr, LPush, LRange10, LRange100, 其中LRange10和&LRange100都是调用LRange操作,不过他们的数量不同而已。以下是我在这些文件夹里面进行的操作。
新开一个终端:
go test -test.bench='.*' & redis-go-driver-benchmark.txt
./grep_data.sh
grep_data是我写的一个脚本:
for i in AlphazeroRedis GaryburdRedigo GosexyRedis Simonz05Godis TcglRedis
grep $i redis-go-driver-benchmark.txt
| awk '{print $3}' & $i
这个脚本的作用就是将AlphazeroRedis、GaryburdRedigo、GosexyRedis、Simonz05Godis、TcglRedis等的测试数据从redis-go-driver-benchmark.txt提取出来,也就是他们各自操作的数据,然后写入以他们名字命名的文件里面。我们可以打开AlphazeroRedis看一下,
这些数据依次对应Ping, Set, Get, Incr, LPush, LRange10, LRange100的每次操作所需要的纳秒时间。我写了一个R的小程序来把这些数据显示到一个图上面,对R不是很熟悉,希望了解R的大牛指正。下面上代码:
png(filename="redis的最佳go语言驱动--使用格通测试的数据.png",width=1400, height=900)
Sys.setlocale(, "zh_CN.UTF-8")
oldpar &- par(lwd=4)
AlphazeroRedis &- read.table("AlphazeroRedis")
GaryburdRedigo &- read.table("GaryburdRedigo")
GosexyRedis &- read.table("GosexyRedis")
Simonz05Godis &- read.table("Simonz05Godis")
TcglRedis &- read.table("TcglRedis")
plot(AlphazeroRedis$V1, type="o", ylim = c(0, 360000), col = "black", axes=FALSE, ann=FALSE)
text(2, AlphazeroRedis$V1[2], cex=2, pos=3, col="black", "AlphazeroRedis")
axis(1, at=1:8, lab=c("Ping","Set","Get","Incr", "LPush", "LRange10", "LRange100", ""))
axis(2, las=0, at=40000*0: 360000)
title(xlab="操作", col = "black")
title(ylab="每个操作多少纳秒", col = "black")
title(main = "5个Redis的Go语言驱动操作比较--使用格通测试的数据")
lines(GaryburdRedigo, col = "red")
text(6, GaryburdRedigo$V1[6]-10000, cex=2, pos=1, col="red", "GaryburdRedigo")
lines(GosexyRedis, col = "blue")
text(2, GosexyRedis$V1[2], pos=1,col="blue", cex=2, "GosexyRedis")
lines(Simonz05Godis, col = "yellow")
text(4, Simonz05Godis$V1[4]+7000,pos=3, col="yellow",cex=2, "Simonz05Godis")
lines(TcglRedis, col = "gray")
text(3, TcglRedis$V1[3],pos=1,cex=2, col="gray", "TcglRedis")
par(oldpar)
保存为go-redis-getongs-data.R,用R来调用这个文件:
&source("go-redis-getongs-data.R")
在目录下面会生成一个叫&redis的最佳go语言驱动--使用格通测试的数据.png&的文件,我特意把图给放大,以便能够清楚看到线条的走向,图有点大,可能在这里显示不正确:
在的README.md有gosexy测试的数据,我修改了上面的go-redis-getongs-data.R文件,把gosexy测试的数据整理到图上去:
2副图可以看出,tcgl无疑是5个中耗时最多的。在我测试的数据中,GosexyRedis几乎赢得了所有的测试(除了LRange100输给了GaryburdRedigo),GaryburdRedigo基本上是排老二。而使用gosexy的数据,除了tcgl,其他4个的数据相差不大,而GaryburdRedigo还是赢得了LRange100测试,说明在数量比较大的list方面,GaryburdRedigo是十分有优势的。
从上面的数据可以知道,set, get, incr,lpush的操作耗时都在40ms左右,那就是1s里面能够操作25000次左右。我自己算了一下,吓了一跳, 好像比其他使用案例高了一个数量级(有错希望指正了)。
上面的测试只涉及部分的redis操作,在整体对redis的支持方面,还是需要继续添加其他功能测试。毕竟现在Go才开始发展,还需要继续添砖加瓦。各位看完后也可以自己动手测试一下。
转贴请注明来自:
阅读(...) 评论()
随笔 - 16163
评论 - 1398}

我要回帖

更多关于 golang redis 队列 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信