Golang redis 学习指南
安装
我使用的是 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 学习指南的更多相关文章
- redis 学习指南
一.介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.一个高性能的key-value数据库.并提供多种语言的API.说到Key-Value数据库NoSQL数 ...
- redis学习指南
一.redis安装 # 安装最新版 yum install -y epel-release vim atop htop net-tools git wget gcc-c++ yum clean all ...
- Java工程师学习指南第7部分:重新学习MySQL与Redis
本文整理了微信公众号[Java技术江湖]发表和转载过的Mysql和Redis相关优质文章,想看到更多Java技术文章,就赶紧关注本公众号吧吧. 大白话说说mysql 面试官:给我说说你平时是如何优化M ...
- 学习笔记之Shell脚本学习指南 & sed与awk & 正则表达式
正则表达式_百度百科 http://baike.baidu.com/link?url=ybgDrN2WQQKN64_gu-diCqdeDqL8LQ-jiQ-ftzzPaNUa9CmgBRDNnyx50 ...
- Go Revel 学习指南
Go Revel 学习指南 CONTROLLERS(控制器) Routing(路由)http://www.cnblogs.com/hangxin1940/p/3267065.html Paramete ...
- Redis 小白指南(一)- 简介、安装、GUI 和 C# 驱动介绍
Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍 目录 简介 安装 入门指令 GUI 工具 C# 驱动介绍 简介 ANSI C 编写,开源,基于内存,可持久化,一个键值对的数据库, ...
- Redis 小白指南(二)- 基础命令和五大类型:字符串、散列、列表、集合和有序集合
Redis 小白指南(二)- 基础命令和五大类型:字符串.散列.列表.集合和有序集合 引言 目录 基础命令 字符串类型 散列类型 列表类型 集合类型 有序集合类型 基础命令 1.获得符合规则的键名列表 ...
- Redis学习笔记(二)Redis支持的5种数据类型的总结之String和Hash
引言 在Redis学习笔记(一)中我们已经会安装并且简单使用Redis了,接下来我们一起来学习下Redis支持的5大数据类型. 简介 Redis是REmote DIctionary Server(远程 ...
- Redis学习笔记(一)关于在windows64位环境下的安装学习使用
前言 由于工作需要,目前我正在学习使用Redis.我当时学习Redis就从网上下载了点资料就开始学习了.入门看的是<REDIS入门指南>,这本书个人觉得很适合新手用来学习接触.根据书上的引 ...
随机推荐
- ClassLoad
是什么 用来加载 Class 的.它负责将 Class 的字节码形式转换成内存形式的 Class 对象.字节码可以来自于磁盘文件 .class,也可以是 jar 包里的 .class,也可以来自远程服 ...
- 2019年9月2日,亲自最新JDK12.0.2和JRE1.8.0的下载和配置(64bit),被其他教程坑了几圈忍不住自己写一篇
前因/ 新买了电脑,想在家写前端页面,看到最新版的JDK12.0.2和JRE1.8.0,就想着要用就用最新的,才对得起我的I9电脑.本人也是半生不熟,公司用的都是前辈配置好的环境,并且是JDK8很老了 ...
- SpringMVC开发RESTful接口
概念: 什么是REST? REST是Representational State Transfer的缩写.翻译为"表现层状态转化",restful是一种接口设计风格,它不是一个协议 ...
- Bugku-CTF之前女友(SKCTF)
Day35 前女友(SKCTF) http://123.206.31.85:49162/ flag格式:SKCTF{xxxxxxxxxxxxxxxxxx}
- Linux 改变文件的所有者
平时看不惯文件或文件夹是root权限,当然这些文件不是系统文件时还带一把锁. 改变root权限命令,假设用户名为wmz,该root权限为wmz权限,就是去掉碍眼的那把锁: sudo chmod wmz ...
- 常见的一些mysql多表操作收集(备份)
原帖地址:https://blog.csdn.net/qq_37248648/article/details/78468291 多表操作框架 SELECT A.ID, A.NUMBER, A.PRIC ...
- Java - Test - TestNG: Idea 添加 TestNG 依赖
1. 概述 Idea 开发的 maven 添加 testng 依赖 2. 背景 最近复习 TestNG 尝试搭建环境 发现教材和网上很多的教程, 都是 eclipse 的 我用的是 idea 这个貌似 ...
- C#中的循环:while do...while for
循环:重复将相同或类似规律的代码进行反复执行 减少代码冗余 可维护 可扩展 while(bool) { ...; } 代码块中可以使用break或者continue中断 break:中断整个循环 ...
- 每天进步一点点------如何实现Sobel Edge Detector? (Image Processing) (C/C++)
使用C與C++/CLI實現Sobel Edge Detector. http://www.cnblogs.com/oomusou/archive/2008/07/23/sobel_edge_detec ...
- yii2的防御csrf攻击机制
csrf,中文名称:跨站请求伪造,可以在百度上搜索资料,详细了解这一方面的概念.对于我们是非常有帮助的.yii2的csrf的实现功能是在yii\web\request类实现功能的.request类中的 ...