Go go-redis应用
go-redis是 Go 语言的一个流行的 Redis 客户端库,它提供了丰富的功能来与 Redis 数据库进行交互。
1、简单应用
package mainimport ("context""fmt""log""github.com/redis/go-redis/v9"
)func main() {ctx := context.Background()rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "", // no password setDB: 0, // use default DB})// 设置值err1 := rdb.Set(ctx, "your_key1", "your_value1", 0).Err()if err1 != nil {log.Fatalf("无法设置键值: %v", err1)}// 获取值val, _ := rdb.Get(ctx, "your_key1").Result()fmt.Println("your_key1: ", val)err2 := rdb.LPush(ctx, "your_key2", 111, 222, 333, "444").Err()if err2 != nil {log.Fatalf("无法推送到列表: %v", err2)}// 循环处理邮件队列for {// 从 Redis 队列中获取邮件email, err := rdb.RPop(ctx, "your_key2").Result()if err == redis.Nil {// 队列为空,退出循环fmt.Println("电子邮件队列为空。")break} else if err != nil {log.Fatalf("无法从队列中获取电子邮件: %v", err)} else {fmt.Println(email)}}
}
2、连接池管理
使用 go-redis 可以方便地管理 Redis 连接池,确保高效的连接复用。
package mainimport ("context""fmt""github.com/redis/go-redis/v9"
)func main() {var ctx = context.Background()// 创建一个新的 Redis 客户端client := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,PoolSize: 10, // 设置连接池大小})// 使用客户端pong, err := client.Ping(ctx).Result()if err != nil {panic(err)}fmt.Println(pong) // 输出 PONG
}
3、管道和事务
go-redis 支持管道(pipelines)和事务(transactions),可以批量执行命令,减少网络往返次数。
事务(Transactions)
事务在 Redis 中用来执行一系列命令,这些命令被打包在一起,然后一起执行。如果在执行过程中遇到错误,整个事务将被取消。事务可以保证操作的原子性。
package mainimport ("context""fmt""github.com/redis/go-redis/v9"
)func main() {var ctx = context.Background()// 创建 Redis 客户端client := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})// 检查连接pong, err := client.Ping(ctx).Result()if err != nil {fmt.Printf("连接失败: %v", err)return}fmt.Printf("连接成功: %s\n", pong)key1 := "key1"key2 := "key2"// 使用 WATCH 命令监视键err = client.Watch(ctx, func(tx *redis.Tx) error {// 事务中的命令// SetNX函数:当该键不存在时才设置。如果键已经存在,命令将不执行任何操作。第三个参数为设置过期时间,0表示永不过期k1, err := tx.SetNX(ctx, key1, "value1", 0).Result() // 仅当 key1 不存在时设置值if err != nil {return err}if k1 {fmt.Println("key1 设置成功")} else {fmt.Println("key1 已存在,未进行设置操作")}k2, err := tx.SetNX(ctx, key2, "value2", 0).Result() // 仅当 key2 不存在时设置值if err != nil {return err}if k2 {fmt.Println("key2 设置成功")} else {fmt.Println("key2 已存在,未进行设置操作")}// 使用 MULTI 命令开始事务pipe := tx.Pipeline()// 将命令添加到事务队列_, err = pipe.Set(ctx, key1, "value1", 0).Result()if err != nil {return err}_, err = pipe.Set(ctx, key2, "value2", 0).Result()if err != nil {return err}// 使用 EXEC 命令执行事务_, err = pipe.Exec(ctx)if err != nil {return err}return nil}, key1, key2)if err != nil {if err == redis.TxFailedErr {fmt.Println("事务失败,可能因为键被其他客户端修改")} else {fmt.Printf("发生错误: %v", err)}return}// 如果事务成功,获取 key1 和 key2 的值val1, err := client.Get(ctx, key1).Result()if err != nil {fmt.Printf("获取 key1 失败: %v", err)return}val2, err := client.Get(ctx, key2).Result()if err != nil {fmt.Printf("获取 key2 失败: %v", err)return}fmt.Printf("key1: %s, key2: %s\n", val1, val2)
}
使用 Watch 方法监视了两个键 "key1" 和 "key2"。在 Watch 的回调函数中,我们尝试设置这两个键的值,如果设置成功,我们使用 Pipeline 方法将设置操作添加到事务队列中。最后,我们使用 Exec 方法提交事务。
请注意,如果 "key1" 或 "key2" 在我们设置它们之前已经被其他客户端设置,那么事务将不会执行,并且 Watch 方法将返回 redis.TxFailedErr 错误。在实际应用中,你可能需要根据这个错误来决定是否重试事务。
事务&管道
package mainimport ("context""fmt""github.com/redis/go-redis/v9"
)func main() {var ctx = context.Background()// 创建一个新的 Redis 客户端client := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,PoolSize: 10, // 设置连接池大小})// 假设我们想检查并更新的key以及期望的旧值和新值key := "mykey"oldValue := "expectedOldValue"newValue := "newValue"// 事务:使用 MULTI 和 EXEC 命令保证操作的原子性err := client.Watch(ctx, func(tx *redis.Tx) error {// 在事务中获取key的值val, err := tx.Get(ctx, key).Result()if err != nil && err != redis.Nil {return err}// 检查值是否与预期相符if val == oldValue {// 如果相符,尝试更新值_, err := tx.Set(ctx, key, newValue, 0).Result()if err != nil {return err}fmt.Println("更新成功")return nil} else {fmt.Println("键存在,值与预期值不匹配。")return nil // 这里返回nil表示不执行任何操作,事务会因为没有EXEC调用而自动取消}}, key)if err != nil {panic(err)}// 管道:批量发送命令cmds, err := client.Pipelined(ctx, func(pipe redis.Pipeliner) error {pipe.Set(ctx, "key1", "value1", 0)pipe.Get(ctx, "key1")return nil})if err != nil {panic(err)}fmt.Println(cmds) // 输出 [SetResult(string) <nil>, StringResult(value1, nil)]
}
4、发布/订阅模式
发布:
package mainimport ("context""fmt""github.com/redis/go-redis/v9""time"
)func main() {client := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})ctx := context.Background()// 发送消息的循环for {err := client.Publish(ctx, "my_channel", "Hello, Redis!").Err()if err != nil {fmt.Printf("发布消息失败: %v\n", err)return}fmt.Println("消息发布成功")// 每5秒发布一条消息time.Sleep(5 * time.Second)}
}
订阅:
package mainimport ("context""fmt""github.com/redis/go-redis/v9""log""os""os/signal"
)func main() {// 创建 Redis 客户端client := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})ctx := context.Background()// 订阅频道pubsub := client.Subscribe(ctx, "my_channel")// 处理接收到的消息go func() {defer func() {if err := pubsub.Close(); err != nil {log.Printf("关闭订阅失败: %v", err)}}()for {msg, err := pubsub.ReceiveMessage(ctx)if err != nil {log.Printf("接收消息失败: %v", err)return}fmt.Printf("接收到消息: %s\n", msg.Payload)}}()// 等待中断信号以退出sigChan := make(chan os.Signal, 1)signal.Notify(sigChan, os.Interrupt)<-sigChanfmt.Println("正在关闭订阅...")
}
package mainimport ("context""github.com/redis/go-redis/v9""log""os""os/signal""syscall""time"
)var ctx = context.Background()func main() {// 创建 Redis 客户端client := redis.NewClient(&redis.Options{Addr: "localhost:6379",Password: "",DB: 0,})if err := client.Ping(ctx).Err(); err != nil {log.Fatalf("无法连接到 Redis: %v", err)}// 启动订阅者go runSubscriber(client)// 发布者循环发送消息runPublisher(client)// 等待中断信号以优雅退出quit := make(chan os.Signal, 1)signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)<-quitlog.Println("接收到退出信号,正在关闭...")if err := client.Close(); err != nil {log.Fatalf("关闭 Redis 客户端失败: %v", err)}
}func runSubscriber(client *redis.Client) {pubsub := client.Subscribe(ctx, "my_channel")defer func() {if err := pubsub.Close(); err != nil {log.Printf("关闭订阅失败: %v", err)}}()log.Println("订阅者启动,正在监听消息...")for {msg, err := pubsub.ReceiveMessage(ctx)if err != nil {log.Printf("接收消息失败: %v", err)return}log.Printf("接收到消息: %s\n", msg.Payload)}
}func runPublisher(client *redis.Client) {ticker := time.NewTicker(5 * time.Second)defer ticker.Stop()log.Println("发布者启动,将定时发送消息...")for {select {case <-ticker.C:err := client.Publish(ctx, "my_channel", "Hello, Redis!").Err()if err != nil {log.Printf("发布消息失败: %v", err)return}log.Println("消息发布成功")}}
}
相关文章:
Go go-redis应用
go-redis 是 Go 语言的一个流行的 Redis 客户端库,它提供了丰富的功能来与 Redis 数据库进行交互。 1、简单应用 package mainimport ("context""fmt""log""github.com/redis/go-redis/v9" )func main() {ctx : context…...
从混乱到有序:PDM系统如何优化物料编码
在现代制造业中,物料管理是企业运营的核心。物料编码作为物料管理的基础,对于确保物料的准确性、唯一性和高效性至关重要。随着产品种类的不断增加和产品变型的多样化,传统的物料编码管理方式已经不能满足企业的需求。本文将探讨产品数据管理…...
npm发布自己的插件包
要发布自己的插件包到npm,可以按照以下步骤进行操作: 1.创建一个新项目 首先确保你已经安装了Node.js和npm。然后,在你的项目目录中初始化一个新的npm项目:npm init命令会引导你创建一个package.json文件,其中包含你插件包的基本…...
Pygame:新手指南与入门教程
在游戏开发领域,pygame 是一个广受欢迎的 Python 库,它提供了开发二维游戏的丰富工具和方法。这个库让开发者可以较少地关注底层图形处理细节,更多地专注于游戏逻辑和玩法的实现。本文将详细介绍 pygame,包括其安装过程、基本概念、主要功能和一个简单游戏的开发流程。 一…...
动态IP与静态IP的优缺点
在网络连接中,使用动态和静态 IP 地址取决于连接的性质和要求。静态 IP 地址通常更适合企业相关服务,而动态 IP 地址更适合家庭网络。让我们来看看动态 IP 与静态 IP 的优缺点。 1.静态IP的优点: 更好的 DNS 支持:静态 IP 地址在…...
上海市计算机学会竞赛平台2024年1月月赛丙组最大的和
题目描述 给定两个序列 𝑎1,𝑎2,…,𝑎𝑛a1,a2,…,an 与 𝑏1,𝑏2,…,𝑏𝑛b1,b2,…,bn,请从这两个序列中分别各找一个数,要求这两个数的差不超过给…...
C++三大特性之继承,详细介绍
阿尼亚全程陪伴大家学习~ 前言 每个程序员在开发新系统时,都希望能够利用已有的软件资源,以缩短开发周期,提高开发效率。 为了提高软件的可重用性(reusability),C提供了类的继承机制。 1.继承的概念 继承: 指在现有…...
Python推导式详解
引言 推导式(Comprehensions)是Python中一种简洁且强大的语法结构,可以用来生成列表、字典和集合。推导式使得代码更加简洁、易读,同时也更具Pythonic风格。今天我将将详细介绍列表推导式、字典推导式和集合推导式…...
stm32中如何实现EXTI线 0 ~ 15与对应IO口的配置呢?
STM32的EXTI控制器支持19 个外部中断/ 事件请求。每个中断设有状态位,每个中断/ 事件都有独立的触发和屏蔽设置。 STM32的19个外部中断对应着19路中断线,分别是EXTI_Line0-EXTI_Line18: 线0~15:对应外部 IO口的输入中断。 线16&…...
Python 短文本匹配,短文本语义相似度,基于大模型的短文本匹配,基于LLMs的短文本语义相似度识别,短文本语义扩充和匹配
1.任务描述 之前在做疾病相似度匹配的时候,堪称史诗级难题,虽然最后加上规则以及一些nlp模型,取得了差强人意的效果,但是短文本的语义相似度匹配一直属于比较难以攻克的难题 2.思路 随着近年大模型的飞速发展,就之前…...
提升接口性能方式汇总
1,sql 2,缓存,尤其面向用户,如app数据。可用redis咖啡,二级缓存。 充分利用redis,redis数据类型很多,平时场景中结合实际情况,找一下对应的redis实现方案 比如Zset可以排序&#…...
C++中的常见语法糖汇总
C中的语法糖是指使代码更简洁、可读性更高的语言特性和简化的语法。以下是一些常见的C语法糖: 1. 自动类型推导(auto) 使用 auto 关键字可以让编译器自动推导变量的类型,简化变量的声明。 auto x 10; // 编译器推导 x…...
TensorFlow Playground神经网络演示工具使用方法详解
在现代机器学习领域,神经网络无疑是一个重要的研究方向。然而,对于许多初学者来说,神经网络的概念和实际操作可能显得相当复杂。幸运的是,TensorFlow Playground 提供了一个交互式的在线工具,使得我们可以直观地理解和实验神经网络的基本原理。在这篇博客中,我们将详细介…...
【git】subtree 简单教程
git subtree使用案例 😄生命不息,写作不止 🔥 继续踏上学习之路,学之分享笔记 👊 总有一天我也能像各位大佬一样 🏆 博客首页 怒放吧德德 To记录领地 🌝分享学习心得,欢迎指正&am…...
C语言基础:字符串函数使用与剖析
strtok(分割字符串) char * strtok ( char * str, const char * sep ); sep参数是个字符串,定义了用作分隔符的字符集合 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。strtok函数找…...
搭建Vulnhub靶机网络问题(获取不到IP)
搭建好靶场后,在攻击机运行arp-scan -l无法发现靶机IP。 这时候去看下靶机网络有没有问题。 重新启动客户机,一直按e进入安全模式(要是直接开机了就先按shift进入grub界面,再按e)找到ro,将ro改为rw signie…...
Prompt 提示词强大方法论和框架2
自从ChatGPT Chat Generative Pre-trained Transformer于2022年11月30日发布以来,一个新兴的行业突然兴起, 那就是提示工程Prompt engineering,可谓如日冲天。 从简单的文章扩写到RAG,ChatGPT展现了前所未有的惊人能力。 在上一…...
C语言分支和循环(2)
我的相关博客: C语言的分支与循环(1) 1.switch语句 除了 if 语句外,C语⾔还提供了 switch 语句来实现分⽀结构。 switch 语句是⼀种特殊形式的 的 if...else 结构,⽤于判断条件有多个结果的情况。它把多重 else if…...
14.FreeRTOS 流媒体缓存 Stream Buffer
FreeRTOS 中的 Stream Buffer(流媒体缓存) 在实时操作系统(RTOS)中,处理流媒体数据是一项非常关键的任务。FreeRTOS 提供了一种名为 Stream Buffer(流媒体缓存)的机制,用于高效地管…...
利用ffmpeg把视频分解成图片(每秒x张图)再图片合成视频
1. 视频分解成图片 ffmpeg -i rawVideo.mp4 -r 5 -f image2 img/%04d.png-i rawVideo.mp4 输入文件 -r 5 每秒5帧(1秒5张图) 可不写,默认每秒24帧 -f image2 表示输出的格式图像 可不写,默认图像 img/ 图片放在img文件夹下 %04d.png 图片的命名…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇
根据 QYResearch 发布的市场报告显示,全球市场规模预计在 2031 年达到 9848 万美元,2025 - 2031 年期间年复合增长率(CAGR)为 3.7%。在竞争格局上,市场集中度较高,2024 年全球前十强厂商占据约 74.0% 的市场…...
