var rdb *redis.Client
var ctx = context.Background()
func RedisTest() {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
}
context.Context
对象是 Go 语言中用于管理请求范围值、取消信号和截止日期的机制。通过使用 context.Context
对象,可以将上下文相关的信息传递到应用程序的不同部分中,使得这些部分可以更加灵活地响应不同的情况。
在 Go-Redis 中,可以使用 context.Background()
创建一个 context.Context 对象,并将其作为参数传递给 Redis 操作的方法。这样可以允许对操作设置超时、取消等上下文相关的行为
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
// 执行 Redis 操作并设置超时时间
value, err := rdb.Get(ctx, "key").Result()
if err != nil {
if err == redis.Nil {
fmt.Println("Key does not exist")
} else if err == context.DeadlineExceeded {
fmt.Println("Operation timed out")
} else {
panic(err)
}
} else {
fmt.Println("Value:", value)
}
在上述示例中,我们使用 context.WithTimeout()
函数创建了一个带有截止日期的上下文,并将其作为参数传递给 Redis 操作。如果 Redis 操作的执行时间超过了指定的截止日期,操作将会被中止。
func SetDemo() {
// Set
set := rdb.Set(ctx, "goland", "so good", 0)
fmt.Println(set)
}
func GetDemo() {
// Get
res, err := rdb.Get(ctx, "goland").Result()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(res)
}
// SizeDemo 获取键值对数量失败
func SizeDemo() {
count, err := rdb.DBSize(ctx).Result()
if err != nil {
fmt.Println("获取键值对数量失败:", err)
return
}
fmt.Println("Redis 中存储的键值对数量是:", count)
}
// AllKey 获取 Redis 中所有的键名
func AllKey() {
keys, err := rdb.Keys(ctx, "*").Result()
if err != nil {
fmt.Println("获取键名失败:", err)
return
}
fmt.Println(keys)
fmt.Println("Redis 中存储的键值对是:")
//for _, key := range keys {
// value, err := rdb.Get(key).Result()
// if err != nil {
// fmt.Printf("读取键 %s 失败: %v\n", key, err)
// } else {
// fmt.Printf("%s : %s\n", key, value)
// }
//}
}
// MsetDemo 批量设置
func MsetDemo() {
err := rdb.MSet(ctx, "NO1", "Go", "NO2", "C++", "NO3", "JAVA", "NO4", "PYTHON").Err()
if err != nil {
fmt.Println("MSet failed, err: ", err)
return
}
}
// MgetDemo 批量获取
func MgetDemo() {
res1, err := rdb.MGet(ctx, "NO1", "NO2", "NO3", "NO4").Result()
if err != nil {
fmt.Println(err)
return
}
for i, _ := range res1 {
fmt.Println(res1[i])
}
}
// DelDemo 删除键值对
func DelDemo() {
result, err := rdb.Del(ctx, "Chinese").Result()
if err != nil {
fmt.Println("删除键值对失败:", err)
return
}
fmt.Println("已删除的键值对数量:", result)
}
// FlushAllDemo 清空所有键值对
func FlushAllDemo() {
err := rdb.FlushAll(ctx).Err()
if err != nil {
fmt.Println("清空键值对失败:", err)
return
}
fmt.Println("已清空所有键值对")
}
// LpushDemo 从左边添加元素
//LPush 命令常用于构建队列、实现消息发布与订阅等场景,可以将新的元素插入到列表的头部,使得最新的元素在队列中的位置靠前。
func LpushDemo() {
err := rdb.LPush(ctx, "NBAPlayer", "kobe", "kawhi").Err()
if err != nil {
fmt.Println("Push failed", err)
return
}
}
// LRangeDemo 获取list中所有元素
func LRangeDemo() {
val := rdb.LRange(ctx, "NBAPlayer", 0, -1).Val()
fmt.Println(val)
}
// LPopDemo 从list左边弹出一个元素
func LPopDemo() {
res, err := rdb.LPop(ctx, "NBAPlayer").Result()
if err != nil {
fmt.Println("pop failed", err)
return
}
fmt.Println(res)
}
// HSetDemo 添加或修改hash类型key的field的值
func HSetDemo() {
err := rdb.HSet(ctx, "USA", "name", "dsb").Err()
if err != nil {
fmt.Println("Are you kidding? America Government is really sb")
return
}
}
// HGetDemo 获取一个hash类型的key的field的值
func HGetDemo() {
res, err := rdb.HGet(ctx, "USA", "name").Result()
if err != nil {
fmt.Println("Are you kidding? America Government is really sb")
return
}
fmt.Println(res)
}
// HMSetDemo 批量添加多个hash类型key的field值
func HMSetDemo() {
usaMap := map[string]interface{}{"name": "dsb", "name2": "robber"}
err := rdb.HMSet(ctx, "USA", usaMap).Err()
if err != nil {
fmt.Println("Are you kidding? America Government is really sb")
return
}
}
// HMGetDemo 批量获取hash类型key多个field的value值
func HMGetDemo() {
res2 := rdb.HMGet(ctx, "USA", "name2", "name").Val()
fmt.Println(res2)
}
// HGetAllDemo 获取哈希中的所有字段值
func HGetAllDemo() {
hGetAll := rdb.HGetAll(ctx, "USA")
if hGetAll.Err() != nil {
panic(hGetAll.Err())
}
for field, value := range hGetAll.Val() {
fmt.Println("name:", field)
fmt.Println("name2:", value)
}
}
// HDelDemo 删除哈希字段
func HDelDemo() {
hDel := rdb.HDel(ctx, "USA", "name")
if hDel.Err() != nil {
panic(hDel.Err())
}
}
// SAddDemo 向set中添加若干个元素
func SAddDemo() {
err := rdb.SAdd(ctx, "Chinese", "AiGuo", "JingYe", "ChengXin", "YouShan").Err()
if err != nil {
fmt.Println("Are you right? Chinese people are really great", err)
return
}
}
// SMembersDemo 返回set中所有元素s
func SMembersDemo() {
res3 := rdb.SMembers(ctx, "Chinese").Val()
fmt.Println(res3)
}
// SIsMemberDemo 判断元素是否存在于set中
func SIsMemberDemo() {
res4, err := rdb.SIsMember(ctx, "Chinese", "AiGuo").Result() // 这里返回的是bool
if err != nil {
fmt.Println("You're mistaken")
return
}
fmt.Println("I can see that the Chinese are really AiGuo is", res4)
}
// SCardDemo 返回set中元素的个数
func SCardDemo() {
count := rdb.SCard(ctx, "Chinese").Val()
fmt.Printf("The Chinese people have %d virtues\n", count)
}
// SRemDemo 从集合中删除元素
func SRemDemo() {
sRem := rdb.SRem(ctx, "Chinese", "JingYe")
if sRem.Err() != nil {
panic(sRem.Err())
}
}
// ZAddDemo 向 ZSET 中添加元素
func ZAddDemo() {
zAdd := rdb.ZAdd(ctx, "zset",
&redis.Z{Score: 90.0, Member: "Alice"},
&redis.Z{Score: 80.0, Member: "Bob"})
if zAdd.Err() != nil {
panic(zAdd.Err())
}
}
// ZRangeDemo 获取 ZSET 中的元素
func ZRangeDemo() {
zRange := rdb.ZRange(ctx, "zset", 0, -1)
if zRange.Err() != nil {
panic(zRange.Err())
}
for _, member := range zRange.Val() {
fmt.Println(member)
}
}
// ZRemDemo 从 ZSET 中删除元素
func ZRemDemo() {
zRem := rdb.ZRem(ctx, "zset", "Bob")
if zRem.Err() != nil {
panic(zRem.Err())
}
}
// ZScoreDemo 获取指定元素的分值
func ZScoreDemo() {
zScore := rdb.ZScore(ctx, "zset", "Alice")
if zScore.Err() != nil {
panic(zScore.Err())
}
fmt.Println("Score:", zScore.Val())
}
以下是 Redis 中常见数据类型的适用场景:
1. 字符串(String):字符串类型是最基本的数据类型,适用于存储任意类型的数据,例如用户信息、配置信息、计数器等。字符串类型可以设置过期时间,支持对字符串进行追加、覆盖和获取操作。
2. 哈希(Hash):哈希类型适用于存储对象、记录或配置等复杂数据结构。它提供了快速的字段查找和更新操作,可以对单个字段进行读写操作,也可以获取和修改整个哈希表。
3. 列表(List):列表类型适用于存储有序的字符串元素集合,可以在列表的两端进行元素插入和删除操作。它常用于消息队列、任务队列、最新消息列表等场景。
4. 集合(Set):集合类型适用于存储不重复的字符串元素的无序集合。集合提供了高效的成员检查和集合操作,可以用于存储唯一值、标签、关注者等场景。
5. 有序集合(Sorted Set):有序集合类型适用于存储不重复的字符串元素的有序集合。每个元素都关联着一个分数,可以根据分数进行排序。有序集合常用于排行榜、按权重排序的数据等场景。
pipeline是一种提高数据处理效率的技术。Pipeline可以将多个Redis命令打包成一个请求发送给Redis服务器,减少了网络延迟和I/O开销,提高了数据处理效率。
func pipelineDemo() {
//创建Pipeline对象
pipe := rdb.Pipeline()
//向Pipeline中添加Redis命令,与标准的go-redis命令用法相同
pipe.Incr(ctx, "key")
pipe.MGet(ctx, "key1", "key2", "key3")
pipe.HSet(ctx, "hash", "field", "value")
//执行Pipeline命令,一次性将所有Redis命令发送给Redis服务器执行
_, err := pipe.Exec(ctx)
if err != nil {
// handle error
}
//在执行完Pipeline中的所有命令后,返回的结果是一个Redis命令结果数组,数组中的元素顺序对应Pipeline中添加的Redis命令顺序。
}
go-redis库提供了事务功能,可以将多个命令组合在一起作为一个原子操作,保证数据的一致性和完整性
func TxPipelineDemo() {
//创建一个事务对象
tx := rdb.TxPipeline()
defer tx.Close()
//执行事务操作
tx.Set(ctx, "key1", "value1", 0)
tx.Set(ctx, "key2", "value2", 0)
tx.Get(ctx, "key1")
//提交事务
_, err := tx.Exec(ctx)
if err != nil {
// 处理错误
}
}
func pool() {
// 创建 Redis 客户端
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // 如果有密码则填写
PoolSize: 10, // 设置连接池大小为10
MinIdleConns: 5, // 设置最小空闲连接数为5
})
// 关闭连接池
defer client.Close()
// 获取连接
conn := client.Conn(context.Background())
// 关闭连接
defer conn.Close()
// 设置值
err := conn.Set(context.Background(), "key", "value", 0).Err()
if err != nil {
panic(err)
}
// 获取值
value, err := conn.Get(context.Background(), "key").Result()
if err != nil {
panic(err)
}
fmt.Println(value)
}