1. Redis简介

Redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。

 

1.1 特点

  • 支持更多数据类型 
    和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set 有序集合)和hash(哈希类型)。[1]

  • 支持复杂操作 
    这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。[2]

  • 支持主从同步。 
    与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。从盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。Redis的官网地址,非常好记,是redis.io。目前,Vmware在资助着Redis项目的开发和维护。

 

2. redigo

redigo是GO语言的一个redis客户端实现。项目位于https://github.com/garyburd/redigo

 

2.1 安装redigo

redigo没有其他依赖项,可以直接通过go get进行安装 
go get github.com/garyburd/redigo/redis

 

2.2 连接

Conn接口是与Redis协作的主要接口,可以使用Dial,DialWithTimeout或者NewConn函数来创建连接,当任务完成时,应用程序必须调用Close函数来完成

 
  1. package main
  2. import (
  3. "fmt"
  4. "github.com/garyburd/redigo/redis"
  5. )
  6. func main() {
  7. c, err := redis.Dial("tcp", "localhost:6379")
  8. if err != nil {
  9. fmt.Println("Connect to redis error", err)
  10. return
  11. }
  12. defer c.Close()
  13. ...
 

2.3 命令执行

Conn接口中有一个通用方法来执行

n, err := c.Do("APPEND", "key", "value")

Do函数会必要时将参数转化为二进制字符串

Go Type Conversion
[]byte Sent as is
string Sent as is
int, int64 strconv.FormatInt(v)
float64 strconv.FormatFloat(v, 'g', -1, 64)
bool true -> "1", false -> "0"
nil ""
all other types fmt.Print(v)

Redis 命令响应会用以下Go类型表示:

Redis type Go type
error redis.Error
integer int64
simple string string
bulk string []byte or nil if value not present.
array []interface{} or nil if value not present.

可以使用GO的类型断言或者reply辅助函数将返回的interface{}转换为对应类型

 

常用命令[3]

读写

GET key
SET key value [EX seconds] [PX milliseconds] [NX|XX]`

GET取对应键值,如果键值不存在则nil会返回,

 
  1. // 写入值永不过期
  2. _, err = c.Do("SET", "username", "nick")
  3. if err != nil {
  4. fmt.Println("redis set failed:", err)
  5. }
  6. username, err := redis.String(c.Do("GET", "username"))
  7. if err != nil {
  8. fmt.Println("redis get failed:", err)
  9. } else {
  10. fmt.Printf("Got username %v \n", username)
  11. }

输出: 
Got username nick 
SET命令还支持附加参数

  • EX seconds -- 指定过期时间,单位为秒.
  • PX milliseconds -- 指定过期时间,单位为毫秒.
  • NX -- 仅当键值不存在时设置键值.
  • XX -- 仅当键值存在时设置键值. 
    设置键值过期时间为10s
 
  1. // 写入值10S后过期
  2. _, err = c.Do("SET", "password", "123456", "EX", "10")
  3. if err != nil {
  4. fmt.Println("redis set failed:", err)
  5. }
  6. time.Sleep(11 * time.Second)
  7. password, err := redis.String(c.Do("GET", "password"))
  8. if err != nil {
  9. fmt.Println("redis get failed:", err)
  10. } else {
  11. fmt.Printf("Got password %v \n", password)
  12. }

输出 
redis get failed: redigo: nil returned 
批量写入读取

MGET key [key ...]
MSET key value [key value ...]

批量写入读取对象(Hashtable)

HMSET key field value [field value ...]
HMGET key field [field ...]

检测值是否存在

EXISTS key

删除

DEL key [key ...]

设置过期时间

EXPIRE key seconds
 

2.4 管道化(Pipelining)

请求/响应服务可以实现持续处理新请求,即使客户端没有准备好读取旧响应。这样客户端可以发送多个命令到服务器而无需等待响应,最后在一次读取多个响应。这就是管道化(pipelining),这个技术在多年就被广泛使用了。距离,很多POP3协议实现已经支持此特性,显著加速了从服务器下载新邮件的过程。 
Redis很早就支持管道化,所以无论你使用任何版本,你都可以使用管道化技术

连接支持使用Send(),Flush(),Receive()方法支持管道化操作

Send(commandName string, args ...interface{}) error
Flush() error
Receive() (reply interface{}, err error)

Send向连接的输出缓冲中写入命令。Flush将连接的输出缓冲清空并写入服务器端。Recevie按照FIFO顺序依次读取服务器的响应。下例展示了一个简单的管道:

 
  1. c.Send("SET", "foo", "bar")
  2. c.Send("GET", "foo")
  3. c.Flush()
  4. c.Receive() // reply from SET
  5. v, err = c.Receive() // reply from GET

Do方法组合了Send,Flush和 Receive方法。Do方法先写入命令,然后清空输出buffer,最后接收全部挂起响应包括Do方发出的命令的结果。如果任何响应中包含一个错误,Do返回错误。如果没有错误,Do方法返回最后一个响应。如果Do函数的命令参数为"",那么Do方法会清空out缓冲并接受挂起响应而不发送任何命令。

 

2.5 并发

连接并不支持并发调用写入方法(Send,Flush)或者读取方法(Receive)。但是连接支持并发的读写。 
因为Do方法组合了Send,Flush和Receive,Do不可以与其他方法并发执行。

为了能够完全并发访问Redis,在gorouotine中使用线程安全的连接池来获取和释放连接。

 

2.6 发布和订阅(Pub/Sub)

使用Send,Flush和Receive方法来是实现Pub/Sb订阅者。

 
  1. c.Send("SUBSCRIBE", "example")
  2. c.Flush()
  3. for {
  4. reply, err := c.Receive()
  5. if err != nil {
  6. return err
  7. }
  8. // process pushed message
  9. }

PubSubConn类型封装了Conn提供了便捷的方法来实现订阅者模式。Subscribe,PSubscribe,Unsubscribe和PUnsubscribe方法发送和清空订阅管理命令。Receive将一个推送消息 
转化为一个在type switch更为方便使用的类型。

 
  1. psc := redis.PubSubConn{c}
  2. psc.Subscribe("example")
  3. for {
  4. switch v := psc.Receive().(type) {
  5. case redis.Message:
  6. fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
  7. case redis.Subscription:
  8. fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
  9. case error:
  10. return v
  11. }
  12. }
 

2.7 响应辅助函数

Bool,Int,Bytes,String,Strings和Values函数将响应转化为特定类型值。为了允许更方便的封装连接的Do和Receive方法的调用,函数使用第二个参数类型为error类型。如果这个error为non-nil,辅助函数会返回error。如果error为nil,则function转化响应为特定类型。

 
  1. exists, err := redis.Bool(c.Do("EXISTS", "foo"))
  2. if err != nil {
  3. // handle error return from c.Do or type conversion error.
  4. }
  5. The Scan function converts elements of a array reply to Go types:
  6. var value1 int
  7. var value2 string
  8. reply, err := redis.Values(c.Do("MGET", "key1", "key2"))
  9. if err != nil {
  10. // handle error
  11. }
  12. if _, err := redis.Scan(reply, &value1, &value2); err != nil {
  13. // handle error
  14. }
 

2.8 事务支持(Transaction)

MULTI, EXEC,DISCARD和WATCH是构成Redis事务的基础。它们允许在一个步骤中执行一组命令,并提供两点总要保证:

  • 事务中的全部命令被序列化并且顺序执行。它保证不会在Redis事务的处理过程中处理其他客户端发起的请求。这样保证命令如同一个单独操作被执行。
  • 事务中的命令全部被执行或者一个都没有被执行,这样一个Redis事务是原子的。Exec命令触发事务中全部命令的执行,这样如果客户端启动事务后失去连接,在调用MULTI命令后的命令都不会被执行,否则如果EXEC命令被调用,全部操作都会被执行。当配置用只允许添加的文件,Redis保证使用连个独立的write(2) 系统调用来将事务写入磁盘。如果Redis服务崩溃或者被系统管理强行关闭可能只有一部分操作被注册。Redis会在重启时检测到这种状态,并且从中退出附带一个错误。使用redis-check-aoft工具它可以修复只允许添加的文件并且移除事务碎片这样可以让服务重启。

Starting with version 2.2, Redis allows for an extra guarantee to the above two, in the form of optimistic locking in a way very similar to a check-and-set (CAS) operation. This is documented later on this page. 
Usage 
自从版本2.2,Redis允许在以上两点基础上增加一点保证, 
A Redis transaction is entered using the MULTI command. The command always replies with OK. At this point the user can issue multiple commands. Instead of executing these commands, Redis will queue them. All the commands are executed once EXEC is called. 
Calling DISCARD instead will flush the transaction queue and will exit the transaction. 
The following example increments keys foo and bar atomically.

MULTI 
OK 
INCR foo 
QUEUED 
INCR bar 
QUEUED 
EXEC 
1) (integer) 1 
2) (integer) 1 
As it is possible to see from the session above, EXEC returns an array of replies, where every element is the reply of a single command in the transaction, in the same order the commands were issued. 
When a Redis connection is in the context of a MULTI request, all commands will reply with the string QUEUED (sent as a Status Reply from the point of view of the Redis protocol). A queued command is simply scheduled for execution when EXEC is called.

使用Send和Do方法来实现管道化事务

 
    1. c.Send("MULTI")
    2. c.Send("INCR", "foo")
    3. c.Send("INCR", "bar")
    4. r, err := c.Do("EXEC")
    5. fmt.Println(r) // prints [1, 1]

golang--- Redis 操作的更多相关文章

  1. Golang Redis操作

    1. Redis简介 Redis是一个开源的.使用C语言编写的.支持网络交互的.可基于内存也可持久化的Key-Value数据库.   1.1 特点 支持更多数据类型 和Memcached类似,它支持存 ...

  2. docker部署golang+redis聊天室

    博客地址:http://www.niu12.com/article/7#####1.项目源码: https://github.com/ZQCard/webchat#####2.项目构成 websock ...

  3. Atitit.redis操作总结

    Atitit.redis操作总结 1.1. 获取redis所有kv1 1.2. dbsize:返回当前数据库中key的数目 1 1.3. 一起吧所有key列出来1 1.4. Java连接redis   ...

  4. 基于 php-redis 的redis操作

    基于 php-redis 的redis操作 林涛 发表于:2016-5-13 12:12 分类:PHP 标签:php,php-redis,redis 203次 redis的操作很多的,下面的例子都是基 ...

  5. redis操作

    测试环境redis操作 cd /export/servers/redis-2.8.9/src/./redis-cli -n 0 keys keys(pattern):返回满足给定pattern的所有k ...

  6. php的redis 操作类,适用于单台或多台、多组redis服务器操作

    redis 操作类,包括单台或多台.多组redis服务器操作,适用于业务复杂.高性能要求的 php web 应用. redis.php: <?php /* redis 操作类,适用于单台或多台. ...

  7. Redis操作Set工具类封装,Java Redis Set命令封装

    Redis操作Set工具类封装,Java Redis Set命令封装 >>>>>>>>>>>>>>>>& ...

  8. Redis操作List工具类封装,Java Redis List命令封装

    Redis操作List工具类封装,Java Redis List命令封装 >>>>>>>>>>>>>>>> ...

  9. Redis操作Hash工具类封装,Redis工具类封装

    Redis操作Hash工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>> ...

  10. Redis操作字符串工具类封装,Redis工具类封装

    Redis操作字符串工具类封装,Redis工具类封装 >>>>>>>>>>>>>>>>>>& ...

随机推荐

  1. IOS开发学习笔记007-数据结构

    目录: 1.全局变量和局部变量 2.结构体 3.结构体数组 4.结构体做函数参数 5.结构体指针 6.枚举 7.总结 一.全局变量和局部变量 全局变量和局部变量的区别 1. 全局变量,再函数外定义的变 ...

  2. LeetCode——Problem3:Longest Substring Without Repeating Characters

    哎哟我天啊.这道题快折磨死我了.刚开始连题都没看明白,就是不知道substring是什么意思.研究了好长时间才看出来的. 光辉历史呀...菜死了 1.题目 Given a string, find t ...

  3. 使用hibernate建立mysql连接以及生成映射类和配置文件*.cfg.xml

    建立数据库连接 找到window—open perspective—myeclipse database explore空白出右键new注意 driver template 和driver class ...

  4. [oldboy-django][2深入django]Form组件功能: 数据格式验证 + 保留上次输入的值

    1 需求:登录或者注册页面存在以下问题 - 无法记住上次提交的内容,(如果有很多输入项,这样正确项不必重复输入,错误项也能提示错误信息)- 重复进行提交数据的校验(数据是否为空,长度大小等等) 2 d ...

  5. 使用 宝塔面板快速部署Java项目

    环境描述: 服务器系统:CentOS7 64位操作系统 面板版本:宝塔6.9.4 Nginx版本:Nginx 1.16 Tomcat版本:Tomcat7 JDK版本:1.8.0_121 环境部署就不用 ...

  6. 【转载】zookeeper使用和原理探究(一)

    最近开始看到一些公司在使用zookeeper,本身对此了解的很少,这里看到一篇非常好的文章,因此转载 原贴地址:http://www.blogjava.net/BucketLi/archive/201 ...

  7. maven学习(十)——maven生命周期以及插件

    一.生命周期 1.何为生命周期? Maven生命周期就是为了对所有的构建过程进行抽象和统一,包括项目清理,初始化,编译,打包,测试,部署等几乎所有构建步骤 2.Maven三大生命周期 Maven有三套 ...

  8. python发送给邮件 转

    这里用到了Python的两个包来发送邮件: smtplib 和 email . Python 的 email 模块里包含了许多实用的邮件格式设置函数,可以用来创建邮件“包裹”.使用的 MIMEText ...

  9. hdu6212[区间dp] 2017青岛ACM-ICPC网络赛

    原题: BZOJ1032 (原题数据有问题) /*hdu6212[区间dp] 2017青岛ACM-ICPC网络赛*/ #include <bits/stdc++.h> using name ...

  10. Ubuntu 硬盘大小扩展

    注:途中所有图均为配置好补的截图,部分来自其它网页. 1.选择硬盘(SCSI) 2.点击扩展,在弹出框填写期望的硬盘大小(不能比原硬盘大小容量小) 3.进入虚拟机,安装GParted. 命令:sudo ...