用 Go 访问 Redis

Redis 官方并没有提供 Redis 访问包,官网列出来了很多 Go 语言的客户端包,它们都能实现对 Redis 的访问和操作,本文以其中较为人性化的 Redigo 来讲解。

1. Redis 连接

获取项目包:

$ go get github.com/gomodule/redigo

接下来调用 redis.Dial() 连接 Redis 服务器:

package mainimport ("fmt""github.com/gomodule/redigo/redis"
)func main() {c, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("conn redis failed, err:", err)return}defer c.Close()
}

2. Redis 设置和获取字符串

最常用的是 Do() 方法,他可以支持 Redis 的 Set、Get、MSet、MGet、HSet、HGet 等常用命令:

_, err = c.Do("Set", "username", "jim")
if err != nil {fmt.Println(err)return
}

在 Redigo 客户端包中,通过调用 redis.String() 函数来获取字符串:

res, err := redis.String(c.Do("Get", "username"))
if err != nil {fmt.Println(err)return
}
fmt.Println(res)

3. Redis 批量设置

可以用 Do() 批量设置字符串:

_, err = c.Do("MSet", "username", "james", "phone", "18888888888")
if err != nil {fmt.Println("MSet error: ", err)return
}

4. Redis hash 操作

_, err = c.Do("HSet", "names", "jim", "barry")
if err != nil {fmt.Println("hset error: ", err)return
}res3, err := redis.String(c.Do("HGet", "names", "jim"))
if err != nil {fmt.Println("hget error: ", err)return
}
fmt.Println(res3)

5. Redis 设置过期时间

_, err = c.Do("expire", "names", 5)
if err != nil {fmt.Println("expire error: ", err)return
}

6. Redis 队列

// 队列
_, err = c.Do("lpush", "Queue", "jim", "barry", 9)
if err != nil {fmt.Println("lpush error: ", err)return
}
for {r, err := redis.String(c.Do("lpop", "Queue"))if err != nil {fmt.Println("lpop error: ", err)break}fmt.Println(r)
}
res4, err := redis.Int(c.Do("llen", "Queue"))
if err != nil {fmt.Println("llen error: ", err)return
}
fmt.Println(res4)

7. 实现 Redis 连接池功能

为什么使用连接池? Redis也是一种数据库,它基于 C/S 模式,因此如果需要使用,则必须先建立连接。C/S 模式就是一种远程通信的交互模式,因此 Redis服务器可以单独作为一个数据库服务器独立存在。

假设Reds服务器与客户端分处异地,虽然基于内存的 Redis数据库有着超高的性能,但是底层的网络通信却占用了一次数据请求的大量时间。因为,每次数据交互都需要先建立连接。假设一 次数据交互总共用时 30ms,超高性能的 Redis 数据库处理数据所花的时间可能不到 1ms,也就是 说前期的连接占用了 29ms。

连接池则可以实现在客户端建立多个与服务器的连接并且不释放当需要使用连接时,通过一定的算法获取已经建立的连接,使用完后则还给连接池,这就免去了连接服务器所占用的时间

Redigo 客户端包中通过 Pool 对象来建立连接池,其使用方法如下:

  1. 使用 Pool 结构体初始化一个连接池:

    pool = &redis.Pool{MaxIdle:     16,MaxActive:   1024,IdleTimeout: 300,Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "localhost:6379")},}
    
  2. 调用 Do() 方法来设置和获取字符串

    完整代码如下:

    package mainimport ("fmt""github.com/gomodule/redigo/redis"
    )var pool *redis.Poolfunc init() {pool = &redis.Pool{MaxIdle:     16,MaxActive:   1024,IdleTimeout: 300,Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "localhost:6379")},}
    }func main() {c := pool.Get()defer c.Close()_, err := c.Do("Set", "username", "jack")if err != nil {fmt.Println(err)return}r, err := redis.String(c.Do("Get", "username"))if err != nil {fmt.Println(err)return}fmt.Println(r)
    }
    

8. Redis 实现管道操作

请求/响应服务可以实现持续处理新请求。客户端可以发送多个命令到服务器端而无须等待响应,最后再一次性读取多个响应。

Send()、 Flush()、 Receive()方法支持管道化操作。Send()方法用于向连接的输出缓冲中写入 命令。 Flush()方法用于将连接的输出缓冲清空并写入服务器端。 Recevie()方法用于按照 FIFO 顺序依次读取服务器端的响应。示例代码如下:

package mainimport ("fmt""github.com/gomodule/redigo/redis"
)func main() {c, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("conn redis failed, err:", err)return}defer c.Close()c.Send("SET", "username1", "jim")c.Send("SET", "username2", "jack")c.Flush()v, err := c.Receive()fmt.Printf("v:%v,err:%v\n", v, err)v, err = c.Receive()fmt.Printf("v:%v,err:%v\n", v, err)v, err = c.Receive() // 一直等待fmt.Printf("v:%v,err:%v\n", v, err)
}

结果输出:

v:OK,err:<nil>
v:OK,err:<nil>

9. Redis 的并发

在日常开发中,有时会遇到这样的场景:多个人时对同一个数据进行修改,导致并发问题发 生。使用 Redis来解决这个问题是很好的选择。

Redis 管道使得客户端能够用“无等待响应”的方式,来连续发送多条命令请求至 Redis 服务器端,然后服务器端按照请求顺序返回相应的结果

Redis管道( Pipelining)的操作可以理解为并发操作,并通过 Send、 Flush、 Receivel 这3个方法实现客户端可以用Send(方法一次性向服务器发送一个或多个命令。命令发送完毕后, 用 Flush() 方法将缓冲区的命令一次性发送到服务器端,客户端再用 Receive() 方法依次按照先进先出的顺序读取所有命令的结果。 Redis并发的示例如下

package mainimport ("fmt""github.com/gomodule/redigo/redis"
)func main() {conn, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("connect redis error :", err)return}defer conn.Close()conn.Send("HSET", "students", "name", "jim", "age", "19")conn.Send("HSET", "students", "score", "100")conn.Send("HGET", "students", "age")conn.Flush()res1, err := conn.Receive()fmt.Printf("Receive res1:%v \n", res1)res2, err := conn.Receive()fmt.Printf("Receive res2:%v\n", res2)res3, err := conn.Receive()fmt.Printf("Receive res3:%s\n", res3)
}

输出结果:

Receive res1:<nil>
Receive res2:1
Receive res3:%!s(<nil>)

10. Redis 的事务

MULTI、EXEC、 DISCARD 和 WATCH 方法是构成 Redis 事务的基础。使用 Go 语言对 Redis 进行事务操作的本质也是使用这些命令。

  • MULTI:开启事务;
  • EXEC:执行事务;
  • DISCARD:取消事务;
  • WATCH:监视事务中的键变化,一旦有改变则取消事务

示例代码:

package mainimport ("fmt""github.com/gomodule/redigo/redis"
)func main() {conn, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("connect redis error :", err)return}defer conn.Close()conn.Send("MULTI")conn.Send("INCR", "foo")conn.Send("INCR", "bar")r, err := conn.Do("EXEC")fmt.Println(r)
}

【Go】用 Go 访问 Redis相关推荐

  1. windows下vs2013使用C++访问redis

    刚开始在windows下使用c++访问reids各种报错,经过网上到处搜方案,终于可以在windows下访问redis了, 特将注意事项记录下来: 1.获取redis Window下的开发库源码,从g ...

  2. 如何正确访问Redis中的海量数据?服务才不会挂掉!

    来源:https://dwz.cn/pm3pI6MZ 一.前言 有时候我们需要知道线上的Redis的使用情况,尤其需要知道一些前缀的key值,让我们怎么去查看呢?并且通常情况下Redis里的数据都是海 ...

  3. Serverless 解惑——函数计算如何访问 Redis 数据库

    函数计算(Function Compute):函数计算 是事件驱动的全托管计算服务.使用函数计算,您无需采购与管理服务器等基础设施,只需编写并上传代码.函数计算为您准备好计算资源,弹性地可靠地运行任务 ...

  4. Unable to Connect: sPort: 0 C# ServiceStack.Redis 访问 redis

    需求:  对数据库中的不断抓取的文章进行缓存,因此需要定时访问数据,写入缓存中 在捕获到的异常日志发现错误:Unable to Connect: sPort: 0 使用的访问方式是线程池的方式:Poo ...

  5. redis三种架构:主从Cluster哨兵+整合Springboot访问redis

    文章目录 概要:redis集群方案 主从架构 部署主从示例: Redis主从工作原理 Sentinel(哨兵)模式 哨兵的Jedis连接代码: springboot访问哨兵结点 Cluster模式 R ...

  6. redis的那种目录结构能新建么_Serverless 解惑——函数计算如何访问 Redis 数据库...

    函数计算(Function Compute):函数计算 是事件驱动的全托管计算服务.使用函数计算,您无需采购与管理服务器等基础设施,只需编写并上传代码.函数计算为您准备好计算资源,弹性地可靠地运行任务 ...

  7. 使用BeetleX访问redis服务

    BeetleX针对redis访问封了全async/await操作模式,通过它可以更高效地访问redis服务.BeetleX.Redis提供读写分离和多机故意写入处理,同时安全的TLS访问机制,在使用功 ...

  8. 使用jedis访问redis

    使用jedis访问redis 一.服务器端 1.下载 # wget http://download.redis.io/releases/redis-3.2.9.tar.gz 2.解压 # tar xz ...

  9. Springboot2.0访问Redis集群

    Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作高性能的key-value数据库.缓存和消息中间件,掌握它是程序员的必备技能,下面是一个springboot访问redis的 ...

  10. java token redis生成算法_如何访问 Redis 中的海量数据,服务才不会挂掉?

    来源:www.toutiao.com/i6697540366528152077 一.前言 有时候我们需要知道线上的Redis的使用情况,尤其需要知道一些前缀的key值,让我们怎么去查看呢?并且通常情况 ...

最新文章

  1. 游戏外挂设计技术探讨
  2. 项目 接入 在线预览
  3. mysql 一列数据变为一条_SQL 一列数据整合为一条数据
  4. 逻辑斯蒂回归_逻辑回归 - 3 逻辑回归模型
  5. unigui作中间件使用
  6. Asp.net1.0 升级 ASP.NET 2.0 的几个问题总结 (转)
  7. intptr_t 和 uintptr_t类型使用总结
  8. win7下VS2012配置DirectShow+Opencv并且多摄像头采集
  9. smb协议讲解_SMB协议(使用说明+过程详解+抓包分析)
  10. 我的世界java版天空材质_我的世界:天空还能如此真实?四款天空效果对比!网友:我全都要...
  11. 看过这篇文章,终于找到单身的原因了!
  12. JQuery fadeOut()函数与remove()函数合用时不生效的解决办法
  13. android实现刷卡功能,Android 实现银联刷卡机消费后手动签名的功能(示例代码)
  14. php添加商品和显示商品的业务逻辑
  15. 解决警告Presenting view controllers on detached view controllers is discouraged 以及引申
  16. vue修改预设preset
  17. 最不可思议的巧合,这些电影一定是穿越者拍的了!
  18. 数据到底能做什么? ——谷歌、腾讯、高德告诉你答案
  19. 路由控制配置filter-policy export命令解析
  20. 当授权者而非推卸责任者

热门文章

  1. OSPF —— cost值选路
  2. 蓝桥杯 算法训练 逗志芃的危机
  3. 在Ubuntu系统上挂载4T大硬盘的流程
  4. Android ley hash的生成
  5. 支付宝事件溯源:2005年“雅巴“交易再回首
  6. TFDS中检测算法的应用
  7. PS教程:合成复古人物风格海报的技巧
  8. MySQL数据库零基础教学[超详细]
  9. android sdk如何瘦身,给Android应用开发者的十条瘦身建议
  10. 利用粤嵌LinuxGEC6818开发板实现电子相册