Golang redis 操作初体验

前端之家收集整理的这篇文章主要介绍了Golang redis 操作初体验前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

安装

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

  1. go get gopkg.in/redis.v4

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

  1. import "gopkg.in/redis.v4"

基本操作

创建客户端

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

  1. // 创建 redis 客户端
  2. func createClient() *redis.Client {
  3. client := redis.NewClient(&redis.Options{
  4. Addr: "localhost:6379",Password: "",DB: 0,})
  5.  
  6. // 通过 cient.Ping() 来检查是否成功连接到了 redis 服务器
  7. pong,err := client.Ping().Result()
  8. fmt.Println(pong,err)
  9.  
  10. return client
  11. }

String 操作

redis 的 String 操作有:

  1. set(key,value):给数据库名称keystring赋予值value
  2. get(key):返回数据库名称keystringvalue
  3. getset(key,value):给名称keystring赋予上一次的value
  4. mget(key1,key2,…,key N):返回库中多个stringvalue
  5. setnx(key,value):添加string名称key,值为value
  6. setex(key,time,value):向库中添加string,设定过期时间time
  7. mset(key N,value N):批量设置多个string的值
  8. msetnx(key N,value N):如果所有名称key istring都不存在
  9. incr(key):名称keystring1操作
  10. incrby(key,integer):名称keystring增加integer
  11. decr(key):名称keystring1操作
  12. decrby(key,integer):名称keystring减少integer
  13. append(key,value):名称keystring的值附加value
  14. substr(key,start,end):返回名称keystringvalue的子串

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

  1. // String 操作
  2. func stringOperation(client *redis.Client) {
  3. // 第三个参数是过期时间,如果是0,则表示没有过期时间.
  4. err := client.Set("name","xys",0).Err()
  5. if err != nil {
  6. panic(err)
  7. }
  8.  
  9. val,err := client.Get("name").Result()
  10. if err != nil {
  11. panic(err)
  12. }
  13. fmt.Println("name",val)
  14.  
  15.  
  16. // 这里设置过期时间.
  17. err = client.Set("age","20",1 * time.Second).Err()
  18. if err != nil {
  19. panic(err)
  20. }
  21.  
  22. client.Incr("age") // 自增
  23. client.Incr("age") // 自增
  24. client.Decr("age") // 自减
  25.  
  26. val,err = client.Get("age").Result()
  27. if err != nil {
  28. panic(err)
  29. }
  30. fmt.Println("age",val) // age 的值为21
  31.  
  32. // 因为 key "age" 的过期时间是一秒钟,因此当一秒后,此 key 会自动删除了.
  33. time.Sleep(1 * time.Second)
  34. val,err = client.Get("age").Result()
  35. if err != nil {
  36. // 因为 key "age" 已经过期了,因此会有一个 redis: nil 的错误.
  37. fmt.Printf("error: %v\n",err)
  38. }
  39. fmt.Println("age",val)
  40. }

list 操作

redis 的 list 操作有:

  1. rpush(key,value):在名称keylist添加一个值为value的元素
  2. lpush(key,value):在名称keylist添加一个值为value 元素
  3. llen(key):返回名称keylist的长度
  4. lrange(key,end):返回名称keyliststartend之间的元素
  5. ltrim(key,end):截取名称keylist
  6. lindex(key,index):返回名称keylistindex位置的元素
  7. lset(key,index,value):给名称keylistindex位置的元素赋值
  8. lrem(key,count,value):删除countkeylist中值为value的元素
  9. lpop(key):返回并删除名称keylist中的首元素
  10. rpop(key):返回并删除名称keylist中的尾元素
  11. blpop(key1,… key N,timeout):lpop命令的block版本。
  12. brpop(key1,timeout):rpopblock版本。
  13. rpoplpush(srckey,dstkey):返回并删除名称srckeylist的尾元素,并将该元素添加名称dstkeylist的头部

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

  1. // list 操作
  2. func listOperation(client *redis.Client) {
  3. client.RPush("fruit","apple") //在名称为 fruit 的list尾添加一个值为value的元素
  4. client.LPush("fruit","banana") //在名称为 fruit 的list头添加一个值为value的 元素
  5. length,err := client.LLen("fruit").Result() //返回名称为 fruit 的list的长度
  6. if err != nil {
  7. panic(err)
  8. }
  9. fmt.Println("length: ",length) // 长度为2
  10.  
  11. value,err := client.LPop("fruit").Result() //返回并删除名称为 fruit 的list中的首元素
  12. if err != nil {
  13. panic(err)
  14. }
  15. fmt.Println("fruit: ",value)
  16.  
  17. value,err = client.RPop("fruit").Result() // 返回并删除名称为 fruit 的list中的尾元素
  18. if err != nil {
  19. panic(err)
  20. }
  21. fmt.Println("fruit: ",value)
  22. }

set 操作

redis 的 set 操作:

  1. sadd(key,member):向名称keyset添加元素member
  2. srem(key,member) 删除名称keyset中的元素member
  3. spop(key) 随机返回并删除名称keyset中一个元素
  4. smove(srckey,dstkey,member) :移到集合元素
  5. scard(key) :返回名称keyset的基数
  6. sismember(key,member) member是否是名称keyset的元素
  7. sinter(key1,…key N) :求交集
  8. sinterstore(dstkey,(keys)) :求交集并将交集保存到dstkey的集合
  9. sunion(key1,(keys)) :求并集
  10. sunionstore(dstkey,(keys)) :求并集并将并集保存到dstkey的集合
  11. sdiff(key1,(keys)) :求差集
  12. sdiffstore(dstkey,(keys)) :求差集并将差集保存到dstkey的集合
  13. smembers(key) :返回名称keyset的所有元素
  14. srandmember(key) 随机返回名称keyset的一个元素

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

  1. // set 操作
  2. func setOperation(client *redis.Client) {
  3. client.SAdd("blacklist","Obama") // 向 blacklist 中添加元素
  4. client.SAdd("blacklist","Hillary") // 再次添加
  5. client.SAdd("blacklist","the Elder") // 添加新元素
  6.  
  7. client.SAdd("whitelist","the Elder") // 向 whitelist 添加元素
  8.  
  9. // 判断元素是否在集合中
  10. isMember,err := client.SIsMember("blacklist","Bush").Result()
  11. if err != nil {
  12. panic(err)
  13. }
  14. fmt.Println("Is Bush in blacklist: ",isMember)
  15.  
  16.  
  17. // 求交集,即既在黑名单中,又在白名单中的元素
  18. names,err := client.SInter("blacklist","whitelist").Result()
  19. if err != nil {
  20. panic(err)
  21. }
  22. // 获取到的元素是 "the Elder"
  23. fmt.Println("Inter result: ",names)
  24.  
  25.  
  26. // 获取指定集合的所有元素
  27. all,err := client.SMembers("blacklist").Result()
  28. if err != nil {
  29. panic(err)
  30. }
  31. fmt.Println("All member: ",all)
  32. }

hash 操作

redis 的 hash 操作:

  1. hset(key,field,value):向名称keyhash添加元素field
  2. hget(key,field):返回名称keyhashfield对应的value
  3. hmget(key,(fields)):返回名称keyhashfield i对应的value
  4. hmset(key,(fields)):向名称keyhash添加元素field
  5. hincrby(key,integer):将名称keyhashfieldvalue增加integer
  6. hexists(key,field):名称keyhash中是否存在键为field的域
  7. hdel(key,field):删除名称keyhash中键为field的域
  8. hlen(key):返回名称keyhash中元素个数
  9. hkeys(key):返回名称keyhash中所有键
  10. hvals(key):返回名称keyhash中所有键对应的value
  11. hgetall(key):返回名称keyhash中所有的键(field)及其对应的value

go-redis 中的 hash 操作:

  1. // hash 操作
  2. func hashOperation(client *redis.Client) {
  3. client.HSet("user_xys","name","xys"); // 向名称为 user_xys 的 hash 中添加元素 name
  4. client.HSet("user_xys","age","18"); // 向名称为 user_xys 的 hash 中添加元素 age
  5.  
  6. // 批量地向名称为 user_test 的 hash 中添加元素 name 和 age
  7. client.HMSet("user_test",map[string]string{"name": "test","age":"20"})
  8. // 批量获取名为 user_test 的 hash 中的指定字段的值.
  9. fields,err := client.HMGet("user_test","age").Result()
  10. if err != nil {
  11. panic(err)
  12. }
  13. fmt.Println("fields in user_test: ",fields)
  14.  
  15.  
  16. // 获取名为 user_xys 的 hash 中的字段个数
  17. length,err := client.HLen("user_xys").Result()
  18. if err != nil {
  19. panic(err)
  20. }
  21. fmt.Println("field count in user_xys: ",length) // 字段个数为2
  22.  
  23. // 删除名为 user_test 的 age 字段
  24. client.HDel("user_test","age")
  25. age,err := client.HGet("user_test","age").Result()
  26. if err != nil {
  27. fmt.Printf("Get user_test age error: %v\n",err)
  28. } else {
  29. fmt.Println("user_test age is: ",age) // 字段个数为2
  30. }
  31. }

关于连接池

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

  1. client := redis.NewClient(&redis.Options{
  2. Addr: "localhost:6379",PoolSize: 5,})

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

  1. // redis.v4 的连接池管理
  2. func connectPool(client *redis.Client) {
  3. wg := sync.WaitGroup{}
  4. wg.Add(10)
  5.  
  6. for i := 0; i < 10; i++ {
  7. go func() {
  8. defer wg.Done()
  9.  
  10. for j := 0; j < 100; j++ {
  11. client.Set(fmt.Sprintf("name%d",j),fmt.Sprintf("xys%d",0).Err()
  12. client.Get(fmt.Sprintf("name%d",j)).Result()
  13. }
  14.  
  15. fmt.Printf("PoolStats,TotalConns: %d,FreeConns: %d\n",client.PoolStats().TotalConns,client.PoolStats().FreeConns);
  16. }()
  17. }
  18.  
  19. wg.Wait()
  20. }

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

  1. PoolStats,TotalConns: 5,FreeConns: 1
  2. PoolStats,FreeConns: 2
  3. PoolStats,FreeConns: 3
  4. PoolStats,FreeConns: 4
  5. PoolStats,FreeConns: 5

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

完整示例

  1. //
  2. // author xiongyongshun
  3. // project go_redis
  4. // version 1.0
  5. // created 16/10/6 03:49
  6. //
  7. package main
  8.  
  9. import (
  10. "fmt"
  11. "gopkg.in/redis.v4"
  12. "time"
  13. "sync"
  14. )
  15.  
  16. func main() {
  17. client := createClient()
  18. defer client.Close()
  19.  
  20. stringOperation(client)
  21. listOperation(client)
  22. setOperation(client)
  23. hashOperation(client)
  24.  
  25. connectPool(client)
  26.  
  27. }
  28.  
  29. // 创建 redis 客户端
  30. func createClient() *redis.Client {
  31. client := redis.NewClient(&redis.Options{
  32. Addr: "localhost:6379",})
  33.  
  34. pong,err)
  35.  
  36. return client
  37. }
  38.  
  39.  
  40. // String 操作
  41. func stringOperation(client *redis.Client) {
  42. // 第三个参数是过期时间,val)
  43. }
  44.  
  45. // list 操作
  46. func listOperation(client *redis.Client) {
  47. client.RPush("fruit",value)
  48. }
  49.  
  50. // set 操作
  51. func setOperation(client *redis.Client) {
  52. client.SAdd("blacklist",all)
  53. }
  54.  
  55.  
  56. // hash 操作
  57. func hashOperation(client *redis.Client) {
  58. client.HSet("user_xys",age) // 字段个数为2
  59. }
  60. }
  61.  
  62. // redis.v4 的连接池管理
  63. func connectPool(client *redis.Client) {
  64. wg := sync.WaitGroup{}
  65. wg.Add(10)
  66.  
  67. for i := 0; i < 10; i++ {
  68. go func() {
  69. defer wg.Done()
  70.  
  71. for j := 0; j < 100; j++ {
  72. client.Set(fmt.Sprintf("name%d",client.PoolStats().FreeConns);
  73. }()
  74. }
  75.  
  76. wg.Wait()
  77. }

猜你在找的Go相关文章