golang实现Redis客户端操作的高效插件库godis的使用

golang实现Redis客户端操作的高效插件库godis的使用

godis简介

godis是一个用Golang实现的Redis客户端库,参考了Jedis的设计。这个库实现了大多数Redis命令,包括普通Redis命令、集群命令、哨兵命令、管道命令和事务命令。

如果你曾经使用过Jedis,那么你可以轻松使用godis,因为godis的方法几乎与Jedis相同。特别值得一提的是,godis实现了单机模式和集群模式下的分布式锁,性能比Redisson更好。

特性

  • 集群支持
  • 管道操作
  • 事务支持
  • 分布式锁
  • 其他功能正在开发中

安装

使用go get安装:

go get -u github.com/piaohao/godis

或者使用go.mod:

require github.com/piaohao/godis latest

快速开始

1. 基础示例

package main

import (
    "github.com/piaohao/godis"
)

func main() {
    // 创建Redis客户端连接
    redis := godis.NewRedis(&godis.Option{
        Host: "localhost",
        Port: 6379,
        Db:   0,
    })
    defer redis.Close()
    
    // 设置键值
    redis.Set("godis", "1")
    
    // 获取键值
    arr, _ := redis.Get("godis")
    println(arr)
}

2. 使用连接池

package main

import (
    "github.com/piaohao/godis"
)

func main() {
    option := &godis.Option{
        Host: "localhost",
        Port: 6379,
        Db:   0,
    }
    
    // 创建连接池
    pool := godis.NewPool(&godis.PoolConfig{}, option)
    
    // 从连接池获取连接
    redis, _ := pool.GetResource()
    defer redis.Close()
    
    redis.Set("godis", "1")
    arr, _ := redis.Get("godis")
    println(arr)
}

3. 发布订阅

package main

import (
    "github.com/piaohao/godis"
    "time"
)

func main() {
    option := &godis.Option{
        Host: "localhost",
        Port: 6379,
        Db:   0,
    }
    
    pool := godis.NewPool(&godis.PoolConfig{}, option)
    
    // 启动订阅协程
    go func() {
        redis, _ := pool.GetResource()
        defer redis.Close()
        
        pubsub := &godis.RedisPubSub{
            OnMessage: func(channel, message string) {
                println(channel, message)
            },
            OnSubscribe: func(channel string, subscribedChannels int) {
                println(channel, subscribedChannels)
            },
            OnPong: func(channel string) {
                println("recieve pong")
            },
        }
        redis.Subscribe(pubsub, "godis")
    }()
    
    time.Sleep(1 * time.Second)
    
    {
        // 发布消息
        redis, _ := pool.GetResource()
        defer redis.Close()
        redis.Publish("godis", "godis pubsub")
        redis.Close()
    }
    
    time.Sleep(1 * time.Second)
}

4. 集群操作

package main

import (
    "github.com/piaohao/godis"
    "time"
)

func main() {
    // 创建Redis集群客户端
    cluster := godis.NewRedisCluster(&godis.ClusterOption{
        Nodes:             []string{"localhost:7000", "localhost:7001", "localhost:7002", "localhost:7003", "localhost:7004", "localhost:7005"},
        ConnectionTimeout: 0,
        SoTimeout:         0,
        MaxAttempts:       0,
        Password:          "",
        PoolConfig:        &godis.PoolConfig{},
    })
    
    cluster.Set("cluster", "godis cluster")
    reply, _ := cluster.Get("cluster")
    println(reply)
}

5. 管道操作

package main

import (
    "github.com/piaohao/godis"
    "time"
)

func main() {
    option := &godis.Option{
        Host: "localhost",
        Port: 6379,
        Db:   0,
    }
    
    pool := godis.NewPool(&godis.PoolConfig{}, option)
    redis, _ := pool.GetResource()
    defer redis.Close()
    
    // 创建管道
    p := redis.Pipelined()
    
    // 添加命令到管道
    infoResp, _ := p.Info()
    timeResp, _ := p.Time()
    
    // 执行管道中的所有命令
    p.Sync()
    
    // 获取结果
    timeList, _ := timeResp.Get()
    println(timeList)
    
    info, _ := infoResp.Get()
    println(info)
}

6. 事务操作

package main

import (
    "github.com/piaohao/godis"
    "time"
)

func main() {
    option := &godis.Option{
        Host: "localhost",
        Port: 6379,
        Db:   0,
    }
    
    pool := godis.NewPool(nil, option)
    redis, _ := pool.GetResource()
    defer redis.Close()
    
    // 开启事务
    p, _ := redis.Multi()
    
    // 添加命令到事务
    infoResp, _ := p.Info()
    timeResp, _ := p.Time()
    
    // 执行事务
    p.Exec()
    
    // 获取结果
    timeList, _ := timeResp.Get()
    println(timeList)
    
    info, _ := infoResp.Get()
    println(info)
}

7. 分布式锁

单机Redis锁

package main

import (
    "github.com/piaohao/godis"
    "time"
)

func main() {
    // 创建锁管理器
    locker := godis.NewLocker(&godis.Option{
        Host: "localhost",
        Port: 6379,
        Db:   0,
    }, &godis.LockOption{
        Timeout: 5*time.Second,
    })
    
    // 尝试获取锁
    lock, err := locker.TryLock("lock")
    if err == nil && lock!=nil {
        // 执行业务代码
        // ...
        
        // 释放锁
        locker.UnLock(lock)
    }
}

Redis集群锁

package main

import (
    "github.com/piaohao/godis"
    "time"
)

func main() {
    // 创建集群锁管理器
    locker := godis.NewClusterLocker(&godis.ClusterOption{
        Nodes:             []string{"localhost:7000", "localhost:7001", "localhost:7002", "localhost:7003", "localhost:7004", "localhost:7005"},
        ConnectionTimeout: 0,
        SoTimeout:        0,
        MaxAttempts:      0,
        Password:         "",
        PoolConfig:       &godis.PoolConfig{},
    }, &godis.LockOption{
        Timeout: 5*time.Second,
    })
    
    // 尝试获取锁
    lock, err := locker.TryLock("lock")
    if err == nil && lock!=nil {
        // 执行业务代码
        // ...
        
        // 释放锁
        locker.UnLock(lock)
    }
}

许可证

godis采用MIT许可证,100%免费且开源。

感谢

  • [jedis] - Java实现的流行Redis客户端
  • [gf] - Golang实现的优秀Web框架
  • [go-commons-pool] - 参考了Apache Common Pool

联系方式

piao.hao@qq.com


更多关于golang实现Redis客户端操作的高效插件库godis的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang实现Redis客户端操作的高效插件库godis的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用godis实现高效Redis客户端操作

godis是一个高性能的Go语言Redis客户端库,它提供了简洁易用的API来操作Redis数据库。下面我将详细介绍如何使用godis库进行高效的Redis操作。

安装godis

首先需要安装godis库:

go get github.com/redis/go-redis/v9

基本使用

1. 连接Redis

package main

import (
	"context"
	"fmt"
	"github.com/redis/go-redis/v9"
)

func main() {
	// 创建Redis客户端
	rdb := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379", // Redis地址
		Password: "",               // 密码
		DB:       0,                // 数据库编号
	})

	// 测试连接
	ctx := context.Background()
	pong, err := rdb.Ping(ctx).Result()
	if err != nil {
		panic(err)
	}
	fmt.Println(pong) // 输出: PONG
}

2. 基本操作示例

// 设置键值
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
	panic(err)
}

// 获取值
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
	panic(err)
}
fmt.Println("key", val)

// 设置带过期时间的键
err = rdb.Set(ctx, "key2", "value", 10*time.Second).Err()
if err != nil {
	panic(err)
}

// 删除键
rdb.Del(ctx, "key")

// 检查键是否存在
exists, err := rdb.Exists(ctx, "key").Result()
if err != nil {
	panic(err)
}
fmt.Println(exists) // 0表示不存在

高级功能

1. 管道(Pipeline)操作

管道可以一次性发送多个命令到Redis服务器,减少网络往返时间:

pipe := rdb.Pipeline()

// 添加多个命令到管道
pipe.Set(ctx, "key1", "value1", 0)
pipe.Set(ctx, "key2", "value2", 0)
pipe.Incr(ctx, "counter")

// 执行管道中的所有命令
_, err := pipe.Exec(ctx)
if err != nil {
	panic(err)
}

2. 事务(Multi/Exec)

// 使用Watch实现乐观锁
err := rdb.Watch(ctx, func(tx *redis.Tx) error {
	// 获取当前值
	n, err := tx.Get(ctx, "counter").Int()
	if err != nil && err != redis.Nil {
		return err
	}

	// 在Watch期间如果counter被修改,事务会失败
	_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
		pipe.Set(ctx, "counter", n+1, 0)
		return nil
	})
	return err
}, "counter")

if err != nil {
	panic(err)
}

3. 发布/订阅

// 订阅
pubsub := rdb.Subscribe(ctx, "mychannel")
defer pubsub.Close()

// 接收消息
ch := pubsub.Channel()
for msg := range ch {
	fmt.Println(msg.Channel, msg.Payload)
}

// 发布
err := rdb.Publish(ctx, "mychannel", "hello").Err()
if err != nil {
	panic(err)
}

4. 连接池配置

godis内置连接池,可以这样配置:

rdb := redis.NewClient(&redis.Options{
	Addr:     "localhost:6379",
	Password: "",
	DB:       0,
	
	// 连接池配置
	PoolSize:     100,  // 最大连接数
	MinIdleConns: 10,   // 最小空闲连接数
	MaxConnAge:   time.Hour, // 连接最大存活时间
})

性能优化建议

  1. 使用Pipeline:批量操作时使用Pipeline可以减少网络往返时间
  2. 合理配置连接池:根据业务负载调整PoolSize和MinIdleConns
  3. 避免大键:单个键的值不宜过大,会影响性能
  4. 使用合适的数据结构:根据场景选择合适的数据结构(如Hash、Set等)
  5. 复用Context:避免频繁创建新的Context对象

完整示例

package main

import (
	"context"
	"fmt"
	"time"
	"github.com/redis/go-redis/v9"
)

func main() {
	rdb := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
		PoolSize: 100,
	})

	ctx := context.Background()

	// 基本操作
	rdb.Set(ctx, "name", "Alice", 0)
	name, _ := rdb.Get(ctx, "name").Result()
	fmt.Println("name:", name)

	// Hash操作
	rdb.HSet(ctx, "user:1", "name", "Bob", "age", 30)
	user, _ := rdb.HGetAll(ctx, "user:1").Result()
	fmt.Println("user:", user)

	// 列表操作
	rdb.LPush(ctx, "tasks", "task1", "task2")
	tasks, _ := rdb.LRange(ctx, "tasks", 0, -1).Result()
	fmt.Println("tasks:", tasks)

	// 设置操作
	rdb.SAdd(ctx, "tags", "golang", "redis", "database")
	tags, _ := rdb.SMembers(ctx, "tags").Result()
	fmt.Println("tags:", tags)

	// 有序集合
	rdb.ZAdd(ctx, "leaderboard", redis.Z{Score: 100, Member: "player1"})
	leaders, _ := rdb.ZRevRangeWithScores(ctx, "leaderboard", 0, 2).Result()
	fmt.Println("leaders:", leaders)

	// 带过期时间的键
	rdb.Set(ctx, "temp", "value", 10*time.Second)
	ttl, _ := rdb.TTL(ctx, "temp").Result()
	fmt.Println("ttl:", ttl)
}

godis提供了丰富的方法来操作Redis的各种数据结构,通过合理使用可以构建高效的Redis客户端应用。

回到顶部