安装

我使用的是 https://github.com/go-redis/r... 这个 golang 客户端, 因此安装方式如下:

go get gopkg.in/redis.v4

接着在代码中导入此包即可:

import "gopkg.in/redis.v4"

基本操作

创建客户端

通过 redis.NewClient 函数即可创建一个 redis 客户端, 这个方法接收一个 redis.Options 对象参数, 通过这个参数, 我们可以配置 redis 相关的属性, 例如 redis 服务器地址, 数据库名, 数据库密码等.
下面是一个连接的例子:

// 创建 redis 客户端

func createClient() *redis.Client {

client := redis.NewClient(&redis.Options{

Addr: "localhost:6379",

Password: "",

DB: 0,

})

// 通过 cient.Ping() 来检查是否成功连接到了 redis 服务器

pong, err := client.Ping().Result()

fmt.Println(pong, err)

return client

}

String 操作

redis 的 String 操作有:

set(key, value):给数据库中名称为key的string赋予值value

get(key):返回数据库中名称为key的string的value

getset(key, value):给名称为key的string赋予上一次的value

mget(key1, key2,…, key N):返回库中多个string的value

setnx(key, value):添加string,名称为key,值为value

setex(key, time, value):向库中添加string,设定过期时间time

mset(key N, value N):批量设置多个string的值

msetnx(key N, value N):如果所有名称为key i的string都不存在

incr(key):名称为key的string增1操作

incrby(key, integer):名称为key的string增加integer

decr(key):名称为key的string减1操作

decrby(key, integer):名称为key的string减少integer

append(key, value):名称为key的string的值附加value

substr(key, start, end):返回名称为key的string的value的子串

在 go-redis 中, 我们可以直接找到对应的操作方法, 直接上代码:

// String 操作

func stringOperation(client *redis.Client) {

// 第三个参数是过期时间, 如果是0, 则表示没有过期时间.

err := client.Set("name", "xys", 0).Err()

if err != nil {

panic(err)

}

val, err := client.Get("name").Result()

if err != nil {

panic(err)

}

fmt.Println("name", val)

// 这里设置过期时间.

err = client.Set("age", "20", 1 * time.Second).Err()

if err != nil {

panic(err)

}

client.Incr("age") // 自增

client.Incr("age") // 自增

client.Decr("age") // 自减

val, err = client.Get("age").Result()

if err != nil {

panic(err)

}

fmt.Println("age", val) // age 的值为21

// 因为 key "age" 的过期时间是一秒钟, 因此当一秒后, 此 key 会自动被删除了.

time.Sleep(1 * time.Second)

val, err = client.Get("age").Result()

if err != nil {

// 因为 key "age" 已经过期了, 因此会有一个 redis: nil 的错误.

fmt.Printf("error: %v\n", err)

}

fmt.Println("age", val)

}

list 操作

redis 的 list 操作有:

rpush(key, value):在名称为key的list尾添加一个值为value的元素

lpush(key, value):在名称为key的list头添加一个值为value的 元素

llen(key):返回名称为key的list的长度

lrange(key, start, end):返回名称为key的list中start至end之间的元素

ltrim(key, start, end):截取名称为key的list

lindex(key, index):返回名称为key的list中index位置的元素

lset(key, index, value):给名称为key的list中index位置的元素赋值

lrem(key, count, value):删除count个key的list中值为value的元素

lpop(key):返回并删除名称为key的list中的首元素

rpop(key):返回并删除名称为key的list中的尾元素

blpop(key1, key2,… key N, timeout):lpop命令的block版本。

brpop(key1, key2,… key N, timeout):rpop的block版本。

rpoplpush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部

同样地, 在 go-redis 中也可以找到对应的方法, 下面是一个简单的示例:

// list 操作

func listOperation(client *redis.Client) {

client.RPush("fruit", "apple") //在名称为 fruit 的list尾添加一个值为value的元素

client.LPush("fruit", "banana") //在名称为 fruit 的list头添加一个值为value的 元素

length, err := client.LLen("fruit").Result() //返回名称为 fruit 的list的长度

if err != nil {

panic(err)

}

fmt.Println("length: ", length) // 长度为2

value, err := client.LPop("fruit").Result() //返回并删除名称为 fruit 的list中的首元素

if err != nil {

panic(err)

}

fmt.Println("fruit: ", value)

value, err = client.RPop("fruit").Result() // 返回并删除名称为 fruit 的list中的尾元素

if err != nil {

panic(err)

}

fmt.Println("fruit: ", value)

}

set 操作

redis 的 set 操作:

sadd(key, member):向名称为key的set中添加元素member

srem(key, member) :删除名称为key的set中的元素member

spop(key) :随机返回并删除名称为key的set中一个元素

smove(srckey, dstkey, member) :移到集合元素

scard(key) :返回名称为key的set的基数

sismember(key, member) :member是否是名称为key的set的元素

sinter(key1, key2,…key N) :求交集

sinterstore(dstkey, (keys)) :求交集并将交集保存到dstkey的集合

sunion(key1, (keys)) :求并集

sunionstore(dstkey, (keys)) :求并集并将并集保存到dstkey的集合

sdiff(key1, (keys)) :求差集

sdiffstore(dstkey, (keys)) :求差集并将差集保存到dstkey的集合

smembers(key) :返回名称为key的set的所有元素

srandmember(key) :随机返回名称为key的set的一个元素

接下来是 go-redis 的 set 操作:

// set 操作

func setOperation(client *redis.Client) {

client.SAdd("blacklist", "Obama") // 向 blacklist 中添加元素

client.SAdd("blacklist", "Hillary") // 再次添加

client.SAdd("blacklist", "the Elder") // 添加新元素

client.SAdd("whitelist", "the Elder") // 向 whitelist 添加元素

// 判断元素是否在集合中

isMember, err := client.SIsMember("blacklist", "Bush").Result()

if err != nil {

panic(err)

}

fmt.Println("Is Bush in blacklist: ", isMember)

// 求交集, 即既在黑名单中, 又在白名单中的元素

names, err := client.SInter("blacklist", "whitelist").Result()

if err != nil {

panic(err)

}

// 获取到的元素是 "the Elder"

fmt.Println("Inter result: ", names)

// 获取指定集合的所有元素

all, err := client.SMembers("blacklist").Result()

if err != nil {

panic(err)

}

fmt.Println("All member: ", all)

}

hash 操作

redis 的 hash 操作:

hset(key, field, value):向名称为key的hash中添加元素field

hget(key, field):返回名称为key的hash中field对应的value

hmget(key, (fields)):返回名称为key的hash中field i对应的value

hmset(key, (fields)):向名称为key的hash中添加元素field

hincrby(key, field, integer):将名称为key的hash中field的value增加integer

hexists(key, field):名称为key的hash中是否存在键为field的域

hdel(key, field):删除名称为key的hash中键为field的域

hlen(key):返回名称为key的hash中元素个数

hkeys(key):返回名称为key的hash中所有键

hvals(key):返回名称为key的hash中所有键对应的value

hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value

go-redis 中的 hash 操作:

// hash 操作

func hashOperation(client *redis.Client) {

client.HSet("user_xys", "name", "xys"); // 向名称为 user_xys 的 hash 中添加元素 name

client.HSet("user_xys", "age", "18"); // 向名称为 user_xys 的 hash 中添加元素 age

// 批量地向名称为 user_test 的 hash 中添加元素 name 和 age

client.HMSet("user_test", map[string]string{"name": "test", "age":"20"})

// 批量获取名为 user_test 的 hash 中的指定字段的值.

fields, err := client.HMGet("user_test", "name", "age").Result()

if err != nil {

panic(err)

}

fmt.Println("fields in user_test: ", fields)

// 获取名为 user_xys 的 hash 中的字段个数

length, err := client.HLen("user_xys").Result()

if err != nil {

panic(err)

}

fmt.Println("field count in user_xys: ", length) // 字段个数为2

// 删除名为 user_test 的 age 字段

client.HDel("user_test", "age")

age, err := client.HGet("user_test", "age").Result()

if err != nil {

fmt.Printf("Get user_test age error: %v\n", err)

} else {

fmt.Println("user_test age is: ", age) // 字段个数为2

}

}

关于连接池

redis.v4 包实现了 redis 的连接池管理, 因此我们就不需要自己手动管理 redis 的连接了.
默认情况下,
redis.v4 的
redis 连接池大小是10,
不过我们可以在初始化
redis 客户端时自行设置连接池的大小,
例如:

client := redis.NewClient(&redis.Options{

Addr: "localhost:6379",

Password: "",

DB: 0,

PoolSize: 5,

})

通过 redis.Options 的 PoolSize 属性, 我们设置了 redis 连接池的大小为5.
那么接下来我们来看一下这个设置有什么效果吧:

//
redis.v4 的连接池管理

func connectPool(client *redis.Client) {

wg := sync.WaitGroup{}

wg.Add(10)

for i := 0; i < 10; i++ {

go func() {

defer wg.Done()

for j := 0; j < 100; j++ {

client.Set(fmt.Sprintf("name%d", j), fmt.Sprintf("xys%d", j), 0).Err()

client.Get(fmt.Sprintf("name%d", j)).Result()

}

fmt.Printf("PoolStats, TotalConns: %d, FreeConns: %d\n", client.PoolStats().TotalConns, client.PoolStats().FreeConns);

}()

}

wg.Wait()

}

上面的例子启动了10个 routine 来不断向 redis 读写数据, 然后我们通过 client.PoolStats() 获取连接池的信息. 运行这个例子, 输出如下:

PoolStats, TotalConns: 5, FreeConns: 1

PoolStats, TotalConns: 5, FreeConns: 1

PoolStats, TotalConns: 5, FreeConns: 1

PoolStats, TotalConns: 5, FreeConns: 1

PoolStats, TotalConns: 5, FreeConns: 1

PoolStats, TotalConns: 5, FreeConns: 2

PoolStats, TotalConns: 5, FreeConns: 2

PoolStats, TotalConns: 5, FreeConns: 3

PoolStats, TotalConns: 5, FreeConns: 4

PoolStats, TotalConns: 5, FreeConns: 5

通过输出可以看到, 此时最大的连接池数量确实是 5 了, 并且一开始时, 因为 coroutine 的数量大于5, 会造成 redis 连接不足的情况(反映在 FreeConns 上就是前几次的输出 FreeConns 一直是1), 当某个 coroutine 结束后, 会释放此 redis 连接, 因此 FreeConns 会增加.

完整示例

//

// author xiongyongshun

// project go_redis

// version 1.0

// created 16/10/6 03:49

//

package main

import (

"fmt"

"gopkg.in/redis.v4"

"time"

"sync"

)

func main() {

client := createClient()

defer client.Close()

stringOperation(client)

listOperation(client)

setOperation(client)

hashOperation(client)

connectPool(client)

}

// 创建 redis 客户端

func createClient() *redis.Client {

client := redis.NewClient(&redis.Options{

Addr: "localhost:6379",

Password: "",

DB: 0,

PoolSize: 5,

})

pong, err := client.Ping().Result()

fmt.Println(pong, err)

return client

}

// String 操作

func stringOperation(client *redis.Client) {

// 第三个参数是过期时间, 如果是0, 则表示没有过期时间.

err := client.Set("name", "xys", 0).Err()

if err != nil {

panic(err)

}

val, err := client.Get("name").Result()

if err != nil {

panic(err)

}

fmt.Println("name", val)

// 这里设置过期时间.

err = client.Set("age", "20", 1 * time.Second).Err()

if err != nil {

panic(err)

}

client.Incr("age") // 自增

client.Incr("age") // 自增

client.Decr("age") // 自减

val, err = client.Get("age").Result()

if err != nil {

panic(err)

}

fmt.Println("age", val) // age 的值为21

// 因为 key "age" 的过期时间是一秒钟, 因此当一秒后, 此 key 会自动被删除了.

time.Sleep(1 * time.Second)

val, err = client.Get("age").Result()

if err != nil {

// 因为 key "age" 已经过期了, 因此会有一个 redis: nil 的错误.

fmt.Printf("error: %v\n", err)

}

fmt.Println("age", val)

}

// list 操作

func listOperation(client *redis.Client) {

client.RPush("fruit", "apple") //在名称为 fruit 的list尾添加一个值为value的元素

client.LPush("fruit", "banana") //在名称为 fruit 的list头添加一个值为value的 元素

length, err := client.LLen("fruit").Result() //返回名称为 fruit 的list的长度

if err != nil {

panic(err)

}

fmt.Println("length: ", length) // 长度为2

value, err := client.LPop("fruit").Result() //返回并删除名称为 fruit 的list中的首元素

if err != nil {

panic(err)

}

fmt.Println("fruit: ", value)

value, err = client.RPop("fruit").Result() // 返回并删除名称为 fruit 的list中的尾元素

if err != nil {

panic(err)

}

fmt.Println("fruit: ", value)

}

// set 操作

func setOperation(client *redis.Client) {

client.SAdd("blacklist", "Obama") // 向 blacklist 中添加元素

client.SAdd("blacklist", "Hillary") // 再次添加

client.SAdd("blacklist", "the Elder") // 添加新元素

client.SAdd("whitelist", "the Elder") // 向 whitelist 添加元素

// 判断元素是否在集合中

isMember, err := client.SIsMember("blacklist", "Bush").Result()

if err != nil {

panic(err)

}

fmt.Println("Is Bush in blacklist: ", isMember)

// 求交集, 即既在黑名单中, 又在白名单中的元素

names, err := client.SInter("blacklist", "whitelist").Result()

if err != nil {

panic(err)

}

// 获取到的元素是 "the Elder"

fmt.Println("Inter result: ", names)

// 获取指定集合的所有元素

all, err := client.SMembers("blacklist").Result()

if err != nil {

panic(err)

}

fmt.Println("All member: ", all)

}

// hash 操作

func hashOperation(client *redis.Client) {

client.HSet("user_xys", "name", "xys"); // 向名称为 user_xys 的 hash 中添加元素 name

client.HSet("user_xys", "age", "18"); // 向名称为 user_xys 的 hash 中添加元素 age

// 批量地向名称为 user_test 的 hash 中添加元素 name 和 age

client.HMSet("user_test", map[string]string{"name": "test", "age":"20"})

// 批量获取名为 user_test 的 hash 中的指定字段的值.

fields, err := client.HMGet("user_test", "name", "age").Result()

if err != nil {

panic(err)

}

fmt.Println("fields in user_test: ", fields)

// 获取名为 user_xys 的 hash 中的字段个数

length, err := client.HLen("user_xys").Result()

if err != nil {

panic(err)

}

fmt.Println("field count in user_xys: ", length) // 字段个数为2

// 删除名为 user_test 的 age 字段

client.HDel("user_test", "age")

age, err := client.HGet("user_test", "age").Result()

if err != nil {

fmt.Printf("Get user_test age error: %v\n", err)

} else {

fmt.Println("user_test age is: ", age) // 字段个数为2

}

}

// redis.v4 的连接池管理

func connectPool(client *redis.Client) {

wg := sync.WaitGroup{}

wg.Add(10)

for i := 0; i < 10; i++ {

go func() {

defer wg.Done()

for j := 0; j < 100; j++ {

client.Set(fmt.Sprintf("name%d", j), fmt.Sprintf("xys%d", j), 0).Err()

client.Get(fmt.Sprintf("name%d", j)).Result()

}

fmt.Printf("PoolStats, TotalConns: %d, FreeConns: %d\n", client.PoolStats().TotalConns, client.PoolStats().FreeConns);

}()

}

wg.Wait()

}

Golang redis 学习指南的更多相关文章

  1. redis 学习指南

    一.介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.一个高性能的key-value数据库.并提供多种语言的API.说到Key-Value数据库NoSQL数 ...

  2. redis学习指南

    一.redis安装 # 安装最新版 yum install -y epel-release vim atop htop net-tools git wget gcc-c++ yum clean all ...

  3. Java工程师学习指南第7部分:重新学习MySQL与Redis

    本文整理了微信公众号[Java技术江湖]发表和转载过的Mysql和Redis相关优质文章,想看到更多Java技术文章,就赶紧关注本公众号吧吧. 大白话说说mysql 面试官:给我说说你平时是如何优化M ...

  4. 学习笔记之Shell脚本学习指南 & sed与awk & 正则表达式

    正则表达式_百度百科 http://baike.baidu.com/link?url=ybgDrN2WQQKN64_gu-diCqdeDqL8LQ-jiQ-ftzzPaNUa9CmgBRDNnyx50 ...

  5. Go Revel 学习指南

    Go Revel 学习指南 CONTROLLERS(控制器) Routing(路由)http://www.cnblogs.com/hangxin1940/p/3267065.html Paramete ...

  6. Redis 小白指南(一)- 简介、安装、GUI 和 C# 驱动介绍

    Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍 目录 简介 安装 入门指令 GUI 工具 C# 驱动介绍 简介 ANSI C 编写,开源,基于内存,可持久化,一个键值对的数据库, ...

  7. Redis 小白指南(二)- 基础命令和五大类型:字符串、散列、列表、集合和有序集合

    Redis 小白指南(二)- 基础命令和五大类型:字符串.散列.列表.集合和有序集合 引言 目录 基础命令 字符串类型 散列类型 列表类型 集合类型 有序集合类型 基础命令 1.获得符合规则的键名列表 ...

  8. Redis学习笔记(二)Redis支持的5种数据类型的总结之String和Hash

    引言 在Redis学习笔记(一)中我们已经会安装并且简单使用Redis了,接下来我们一起来学习下Redis支持的5大数据类型. 简介 Redis是REmote DIctionary Server(远程 ...

  9. Redis学习笔记(一)关于在windows64位环境下的安装学习使用

    前言 由于工作需要,目前我正在学习使用Redis.我当时学习Redis就从网上下载了点资料就开始学习了.入门看的是<REDIS入门指南>,这本书个人觉得很适合新手用来学习接触.根据书上的引 ...

随机推荐

  1. L2-1 分而治之

    思路 这题的意思是,如果把这些点打掉,其他的点是否能够完全不连通. 用并查集,或者打上标记之后,判断每个点是否还能到达其他点,如果一个点可以到达其他任何点,都应该输出否. 代码 #include &l ...

  2. Tex 一些命令

    1. [!htp] 可以使这个内容跟随在前面的内容后面 假如前面是一段文字,后面是一幅图像,不知什么原因跑到其他地方去了.这时加个[!htp]可以使他紧紧跟在后面 ergdsgagdfgdfgfgaf ...

  3. MySql 怎么存取 Emoji

    01.前言 Emoji 在我们生活中真的是越来越常见了,几乎每次发消息的时候不带个 Emoji,总觉得少了点什么,似乎干巴巴的文字已经无法承载我们丰富的感情了.对于我们开发者来说,如何将 Emoji ...

  4. C#学习笔记之泛型

    泛型的作用和约定 提高性能 拆箱和装箱 从值类型转换为引用类型为装箱,把引用类型转换为值类型为拆箱 装箱和拆箱很容易使用,但是性能损失比较大,尤其是遍历许多项的时候. List<T>不使用 ...

  5. jmeter的使用---JDBC

    一.数据库连接配置JDBC Connection Configuration 二.执行sql语句select statement (1)query type类型介绍 select statement: ...

  6. MomentJS记录下开发中用到的日期

    1.计算当前周一到周日的日期 ​​​​​​​var weekOfday = moment().format('E');//计算今天是这周第几天 var last_monday = moment().s ...

  7. MySQL执行外部sql脚本文件的命令

    sql脚本是包含一到多个sql命令的sql语句,我们可以将这些sql脚本放在一个文本文件中(我们称之为“sql脚本文件”),然后通过相关的命令执行这个sql脚本文件.基本步骤如下:1.创建包含sql命 ...

  8. 09day vi命令详解

    vi有三种模式(互相切换) 1. 命令模式 2. 插入模式(编辑模式) 3. 低行模式 三种模式的切换方法: 使用技巧 vi 文件信息 i --- 进入编辑模式 esc --- 退出编辑模式 :wq ...

  9. python+pygame制作一个可自定义的动态时钟和详解

    1.效果图 2.完整代码 #第1步:导出模块 import sys, random, math, pygame from pygame.locals import * from datetime im ...

  10. hadoop学习笔记(五)hadoop伪分布式集群的搭建

    本文原创,如需转载,请注明作者和原文链接 1.集群搭建的前期准备   见      搭建分布式hadoop环境的前期准备---需要检查的几个点 2.解压tar.gz包 [root@node01 ~]# ...