30天学会Go--第7天 GO语言 Redis 学习与实践(改)

30天学会Go–第7天 GO语言 Redis 学习与实践(改)

文章目录

  • 30天学会Go--第7天 GO语言 Redis 学习与实践(改)
    • 前言
    • 一、Redis 基础知识
      • 1.1 Redis 的核心特性
      • 1.2 Redis 常见使用场景
    • 二、安装 Redis
      • 2.1 在 Linux 上安装
      • 2.2 在 Windows 上安装
      • 2.3 使用 Docker 安装 Redis
    • 三、Redis 常用命令
      • 3.1 基本操作
      • 3.2 数据结构操作
        • 字符串(String)
          • 扩展命令:
        • 哈希(Hash)
          • 扩展命令:
        • 列表(List)
          • 扩展命令:
        • 集合(Set)
          • 扩展命令:
        • 有序集合(Sorted Set)
          • 扩展命令:
    • 四、在 Go 中使用 Redis
      • 4.1 安装 go-redis
      • 4.2 使用示例
        • 代码示例
        • 代码解读
    • 五、Redis 高级功能
      • 5.1 发布/订阅(Pub/Sub)
        • 发布消息
        • 订阅消息
        • 运行逻辑
        • 注意事项
      • 5.2 使用 Redis 实现分布式锁
        • 加锁
        • 解锁
        • 运行逻辑
        • 注意事项
          • 1. 锁的过期时间
          • 2. 解锁的原子性
        • 扩展功能:自动续约
        • 分布式锁的完整实现示例
        • 分布式锁的应用场景
    • 六、总结

前言

Redis 是一个高性能的开源内存数据库,常用于缓存、消息队列、会话存储等场景。它支持多种数据结构(如字符串、哈希、列表、集合、有序集合等)和丰富的操作命令,具有极高的性能和灵活性。

以下是 Redis 的基础知识、安装、常用命令,以及在 Go 中使用 Redis 的方法。

redis中文官方文档指南:redis中文文档

redis的中文官方文档学习笔记很全,推荐去官网学习

30天学会Go–第6天 GO语言 RESTful API 学习与实践:30天学会Go–第6天 GO语言 RESTful API 学习与实践-CSDN博客


一、Redis 基础知识

1.1 Redis 的核心特性

  • 内存存储:所有数据存储在内存中,读写速度极快。
  • 多种数据结构:支持字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)等。
  • 持久化:支持将内存数据持久化到磁盘(RDB 和 AOF 两种方式)。
  • 高可用:支持主从复制、哨兵模式和集群模式,提供高可用性和扩展性。
  • 丰富的功能:如发布/订阅(Pub/Sub)、事务、Lua 脚本等。

1.2 Redis 常见使用场景

  • 缓存:将经常访问的数据存储到 Redis 中,提高读取性能。
  • 会话存储:存储用户登录状态等会话信息。
  • 排行榜:利用有序集合(Sorted Set)实现排行榜功能。
  • 消息队列:使用列表(List)或发布/订阅功能实现消息队列。
  • 分布式锁:利用 Redis 的原子操作实现分布式锁。

二、安装 Redis

2.1 在 Linux 上安装

  1. 下载 Redis:
    wget http://download.redis.io/redis-stable.tar.gz
    
  2. 解压并编译:
    tar xzf redis-stable.tar.gz
    cd redis-stable
    make
    
  3. 启动 Redis:
    src/redis-server
    

2.2 在 Windows 上安装

  1. 下载 Redis for Windows:
    • Redis 官方不支持 Windows,但可以下载社区版:https://github.com/microsoftarchive/redis/releases
  2. 解压后运行 redis-server.exe 启动服务。
  3. 将 Redis 的安装目录添加到系统的环境变量 PATH 中:
    • 打开 系统属性 > 高级系统设置 > 环境变量
    • 在系统变量中找到 Path,点击 编辑
    • 添加 Redis 的安装目录路径(如 C:\Program Files\Redis

2.3 使用 Docker 安装 Redis

  1. 拉取 Redis 镜像:
    docker pull redis
    
  2. 启动 Redis 容器:
    docker run -d --name redis -p 6379:6379 redis
    

三、Redis 常用命令

3.1 基本操作

  • 连接 Redis

    redis-cli
    
  • 设置键值对

    SET key value
    
  • 获取键值

    GET key
    
  • 删除键

    DEL key
    
  • 检查键是否存在

    EXISTS key
    
  • 设置过期时间(秒)

    EXPIRE key seconds
    
  • 查看剩余过期时间

    TTL key
    

3.2 数据结构操作

字符串(String)

字符串是 Redis 中最基本的数据结构,可以存储文本或二进制数据,支持数值操作。

  • 增加值(适用于数值类型)

    • INCR key:将键的值加 1。
      SET counter 10
      INCR counter
      # 输出: (integer) 11
      
    • INCRBY key increment:将键的值增加指定的 increment
      INCRBY counter 5
      # 输出: (integer) 16
      
    • DECR key:将键的值减 1。
      DECR counter
      # 输出: (integer) 15
      
    • DECRBY key decrement:将键的值减少指定的 decrement
      DECRBY counter 3
      # 输出: (integer) 12
      
扩展命令:
  • SET key value:设置键的值。
    SET greeting "Hello"
    
  • GET key:获取键的值。
    GET greeting
    # 输出: "Hello"
    
  • APPEND key value:将 value 追加到键的现有值之后。
    APPEND greeting " World"
    # 输出: (integer) 11
    
  • STRLEN key:获取键值的长度。
    STRLEN greeting
    # 输出: (integer) 11
    

哈希(Hash)

哈希是一个键值对集合,适用于存储对象(如用户信息)。

  • 设置哈希字段

    • HSET key field value:设置哈希表中的字段 field 为指定值 value
      HSET user:1 name "Alice"
      HSET user:1 age 30
      # 输出: (integer) 1
      
  • 获取哈希字段值

    • HGET key field:获取哈希表中字段 field 的值。
      HGET user:1 name
      # 输出: "Alice"
      
  • 获取所有字段和值

    • HGETALL key:获取哈希表中所有字段和值。

      HGETALL user:1
      # 输出: 
      # 1) "name"
      # 2) "Alice"
      # 3) "age"
      # 4) "30"
      
扩展命令:
  • HMSET key field1 value1 field2 value2:同时设置多个字段及其值。

    HMSET user:2 name "Bob" age 25 city "New York"
    
  • HMGET key field1 field2:获取多个字段的值。

    HMGET user:2 name city
    # 输出: 
    # 1) "Bob"
    # 2) "New York"
    
  • HDEL key field:删除哈希表中的一个或多个字段。

    HDEL user:1 age
    # 输出: (integer) 1
    
  • HLEN key:获取哈希表中字段的数量。

    HLEN user:2
    # 输出: (integer) 3
    
  • HEXISTS key field:检查字段是否存在。

    HEXISTS user:2 city
    # 输出: (integer) 1
    

列表(List)

列表是一个链表,支持从两端插入和弹出元素。

  • 从左插入元素

    • LPUSH key value1 value2:将一个或多个值插入到列表的头部。
      LPUSH tasks "Task1" "Task2"
      # 输出: (integer) 2
      
  • 从右插入元素

    • RPUSH key value1 value2:将一个或多个值插入到列表的尾部。
      RPUSH tasks "Task3"
      # 输出: (integer) 3
      
  • 获取列表范围内的元素

    • LRANGE key start stop:获取指定范围的元素(支持负索引)。
      LRANGE tasks 0 -1
      # 输出: 
      # 1) "Task2"
      # 2) "Task1"
      # 3) "Task3"
      
  • 弹出最左边的元素

    • LPOP key:移除并返回列表的第一个元素。

      LPOP tasks
      # 输出: "Task2"
      
扩展命令:
  • RPOP key:移除并返回列表的最后一个元素。
    RPOP tasks
    # 输出: "Task3"
    
  • LLEN key:获取列表的长度。
    LLEN tasks
    # 输出: (integer) 1
    
  • LINDEX key index:获取列表中指定索引的元素。
    LINDEX tasks 0
    # 输出: "Task1"
    

集合(Set)

集合是一个无序的、唯一的元素集合。

  • 添加元素到集合

    • SADD key member1 member2:将一个或多个元素添加到集合。
      SADD fruits "apple" "banana" "cherry"
      # 输出: (integer) 3 
      
  • 获取集合中的所有元素

    • SMEMBERS key:获取集合中的所有元素。
      SMEMBERS fruits
      # 输出: 
      # 1) "apple"
      # 2) "banana"
      # 3) "cherry"
      
  • 检查元素是否存在

    • SISMEMBER key member:检查指定元素是否在集合中。

      SISMEMBER fruits "banana"
      # 输出: (integer) 1
      
扩展命令:
  • SREM key member:移除集合中的一个或多个元素。

    SREM fruits "apple"
    # 输出: (integer) 1
    
  • SCARD key:获取集合中元素的数量。

    SCARD fruits
    # 输出: (integer) 2
    

有序集合(Sorted Set)

有序集合是一个带有分数的集合,分数用于排序。

  • 添加元素并设置分数

    • ZADD key score1 member1 score2 member2:添加一个或多个元素及其分数。
      ZADD leaderboard 100 "Alice" 200 "Bob" 150 "Charlie"
      # 输出: (integer) 3
      
  • 获取有序集合中的元素

    • ZRANGE key start stop [WITHSCORES]:按分数从低到高返回指定范围的元素。
      ZRANGE leaderboard 0 -1 WITHSCORES
      # 输出: 
      # 1) "Alice"
      # 2) "100"
      # 3) "Charlie"
      # 4) "150"
      # 5) "Bob"
      # 6) "200"
      
扩展命令:
  • ZINCRBY key increment member:为指定元素的分数增加 increment
    ZINCRBY leaderboard 50 "Alice"
    # 输出: "150"
    

四、在 Go 中使用 Redis

在 Go 中使用 Redis,通常使用第三方库 go-redis。

4.1 安装 go-redis

运行以下命令安装:

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

4.2 使用示例

以下是一个简单的示例,展示如何在 Go 中使用 Redis。

代码示例
package mainimport ("context""fmt""github.com/redis/go-redis/v9"
)var ctx = context.Background() // 一个通用的、无状态的上下文,用于程序的起点或测试场景func main() {// 1. 连接到 Redisrdb := redis.NewClient(&redis.Options{Addr:     "localhost:6379", // Redis 地址Password: "",               // 如果没有设置密码,留空DB:       0,                // 使用默认数据库})// 2. 写入数据err := rdb.Set(ctx, "key", "value", 0).Err()if err != nil {panic(err)}// 3. 读取数据val, err := rdb.Get(ctx, "key").Result()if err != nil {panic(err)}fmt.Println("key:", val)// 4. 检查键是否存在exists, err := rdb.Exists(ctx, "key").Result()if err != nil {panic(err)}fmt.Println("key exists:", exists)// 5. 删除键err = rdb.Del(ctx, "key").Err()if err != nil {panic(err)}fmt.Println("key deleted")
}
代码解读
  1. 连接 Redis

    • 使用 redis.NewClient 创建 Redis 客户端。
    • 配置地址、密码和数据库编号。
  2. 写入数据

    • 使用 Set 方法写入键值对。
    • 第三个参数为过期时间,0 表示不过期。
  3. 读取数据

    • 使用 Get 方法读取键的值。
  4. 检查键是否存在

    • 使用 Exists 方法检查键是否存在。
  5. 删除键

    • 使用 Del 方法删除键。

五、Redis 高级功能

5.1 发布/订阅(Pub/Sub)

Redis 的发布/订阅(Pub/Sub)功能允许消息的发布者和订阅者通过频道(Channel)进行通信,适用于实时消息推送场景。

发布消息
err := rdb.Publish(ctx, "channel1", "Hello, Redis!").Err()
if err != nil {panic(err)
}
  • Publish:将消息发布到指定的频道 channel1
  • 如果频道没有订阅者,消息会被丢弃,不会存储在 Redis 中。
订阅消息
sub := rdb.Subscribe(ctx, "channel1")
ch := sub.Channel()for msg := range ch {fmt.Println("Received message:", msg.Payload)
}
  • Subscribe:订阅指定的频道 channel1
  • sub.Channel():返回一个通道(Channel),用于接收消息。
  • msg.Payload:获取消息内容。
运行逻辑
  1. 订阅者通过 Subscribe 监听指定频道。
  2. 发布者通过 Publish 向频道发送消息。
  3. 订阅者会实时接收到频道中的消息。
注意事项
  1. 实时性:消息是实时传递的,Redis 不会存储历史消息。
  2. 性能:在高并发场景下,Pub/Sub 的性能可能会成为瓶颈,不适合复杂的消息队列需求。
  3. 替代方案:对于更复杂的消息系统,可以考虑使用 Redis 的 Stream 数据结构或专用的消息队列(如 RabbitMQ、Kafka)。

5.2 使用 Redis 实现分布式锁

分布式锁是一种用于在分布式系统中控制资源访问的机制。Redis 的原子操作(如 SETNXDEL)可以用来实现分布式锁。

加锁
ok, err := rdb.SetNX(ctx, "lock_key", "lock_value", 10*time.Second).Result()
if err != nil || !ok {fmt.Println("Failed to acquire lock")return
}
fmt.Println("Lock acquired, executing task...")
  • SetNX:尝试设置键 lock_key,如果键不存在,则设置成功并返回 true;如果键已存在,则返回 false
  • 10\*time.Second:锁的过期时间,防止因异常情况导致锁无法释放。
  • ok:表示加锁是否成功。

解锁
rdb.Del(ctx, "lock_key")
  • Del:删除键 lock_key,释放锁。

运行逻辑
  1. 使用 SetNX 确保锁的唯一性和原子性。
  2. 设置锁的过期时间,避免因程序崩溃导致锁无法释放。
  3. 任务完成后,删除锁。

注意事项
1. 锁的过期时间
  • 必须设置锁的过期时间,防止因程序崩溃或超时导致锁无法释放。
  • 如果锁的持有时间超过预期,可以使用 Lua 脚本延长锁的过期时间。
2. 解锁的原子性
  • 简单的 Del 存在潜在问题:如果一个客户端意外删除了其他客户端的锁,可能会导致资源竞争。

  • 可以使用 Lua 脚本确保解锁的原子性:

    unlockScript := redis.NewScript(`if redis.call("GET", KEYS[1]) == ARGV[1] thenreturn redis.call("DEL", KEYS[1])elsereturn 0end
    `)_, err := unlockScript.Run(ctx, rdb, []string{"lock_key"}, "lock_value").Result()
    if err != nil {panic(err)
    }
    

扩展功能:自动续约

在某些任务耗时较长的情况下,可以通过定时任务自动续约锁的过期时间:

go func() {ticker := time.NewTicker(5 * time.Second)defer ticker.Stop()for range ticker.C {_, err := rdb.Expire(ctx, "lock_key", 10*time.Second).Result()if err != nil {fmt.Println("Failed to renew lock")return}fmt.Println("Lock renewed")}
}()

分布式锁的完整实现示例

以下是一个完整的分布式锁实现,包括加锁、续约和解锁:

package mainimport ("context""fmt""time""github.com/redis/go-redis/v9"
)var ctx = context.Background()func main() {rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379",})// 加锁lockKey := "lock_key"lockValue := "unique_value"ok, err := rdb.SetNX(ctx, lockKey, lockValue, 10*time.Second).Result()if err != nil || !ok {fmt.Println("Failed to acquire lock")return}fmt.Println("Lock acquired")// 自动续约go func() {ticker := time.NewTicker(5 * time.Second)defer ticker.Stop()for range ticker.C {_, err := rdb.Expire(ctx, lockKey, 10*time.Second).Result()if err != nil {fmt.Println("Failed to renew lock")return}fmt.Println("Lock renewed")}}()// 模拟执行业务逻辑time.Sleep(15 * time.Second)// 解锁unlockScript := redis.NewScript(`if redis.call("GET", KEYS[1]) == ARGV[1] thenreturn redis.call("DEL", KEYS[1])elsereturn 0end`)_, err = unlockScript.Run(ctx, rdb, []string{lockKey}, lockValue).Result()if err != nil {panic(err)}fmt.Println("Lock released")
}

分布式锁的应用场景
  1. 任务调度:确保同一时间只有一个实例执行任务。
  2. 库存扣减:防止多客户端同时更新库存数据。
  3. 限流控制:限制某些资源的并发访问量。

六、总结

Redis 是一个功能强大且灵活的内存数据库,在 Go 中使用 Redis 非常简单。通过学习 Redis 的基本命令和在 Go 中的集成,你可以轻松实现缓存、消息队列、分布式锁等功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/63386.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RK3568笔记3:开发板启动流程

第1章 启动流程 1.1 上电复位 CPU 复位,进入启动模式。系统硬件查找启动设备(如 eMMC)。 1.2 ROM Code 阶段(硬件引导) 在片上 ROM 中存储的启动代码(BootROM)运行。ROM Code 从 eMMC 的 Boo…

重邮+数字信号处理实验三:z变换及离散LTI系统的z域分析

实验目的: ( 1 )学会运用 Matlab 求离散时间信号的有理函数 z 变换的部分分式展开; ( 2 )学会运用 Matlab 分析离散时间系统的系统函数的零极点; ( 3 )学会运用 …

dolphinScheduler 任务调度

#Using docker-compose to Start Server #下载:https://dlcdn.apache.org/dolphinscheduler/3.1.9/apache-dolphinscheduler-3.1.9-src.tar.gz $ DOLPHINSCHEDULER_VERSION3.1.9 $ tar -zxf apache-dolphinscheduler-"${DOLPHINSCHEDULER_VERSION}"-src.t…

node.js中跨域请求有几种实现方法

默认情况下&#xff0c;出于安全考虑&#xff0c;浏览器会实施同源策略&#xff0c;阻止网页向不同源的服务器发送请求或接收来自不同源的响应。 同源策略&#xff1a;协议、域名、端口三者必须保持一致 <!DOCTYPE html> <html lang"en"> <head>&l…

【机器学习】机器学习的基本分类-监督学习-决策树(Decision Tree)

决策树是一种树形结构的机器学习模型&#xff0c;适用于分类和回归任务。它通过一系列基于特征的条件判断来将数据分割为多个子区域&#xff0c;从而预测目标变量的值。 1. 决策树的结构 根节点&#xff08;Root Node&#xff09; 决策树的起点&#xff0c;包含所有样本。根据某…

支付宝租赁小程序助力便捷生活新方式

内容概要 支付宝租赁小程序为现代人带来了许多惊喜&#xff0c;它不仅仅是一个简单的租赁平台&#xff0c;更是生活中不可或缺的好帮手。想象一下&#xff0c;无论你缺少什么&#xff0c;从工具到家居用品&#xff0c;只需轻轻一点&#xff0c;便能轻松找到需要的物品。这个小…

OpenStack介绍

OpenStack概述 OpenStack是一个开源的云计算管理平台软件,主要用于构建和管理云计算环境。它允许企业或组织通过数据中心的物理服务器创建和管理虚拟机、存储资源和网络等云计算服务。其核心组件包括计算(Nova)、网络(Neutron)、存储(Cinder、Swift)等。这些组件相互协作…

ftp服务器搭建-安装、配置及验证

ftp服务器搭建-安装、配置及验证 #安装 sudo apt-get install vsftpd #配置文件 cat > /etc/vsftpd.conf << "EOF" listenNO listen_ipv6YES anonymous_enableNO local_enableYES write_enableYES dirmessage_enableYES use_localtimeYES xferlog_enable…

搭建高可用负载均衡系统:Nginx 与云服务的最佳实践

搭建高可用负载均衡系统&#xff1a;Nginx 与云服务的最佳实践 引言 在项目开发过程中&#xff0c;我们通常在开发和测试阶段采用单机架构进行开发和测试。这是因为在这个阶段&#xff0c;系统的主要目的是功能实现和验证&#xff0c;单机架构足以满足开发人员的日常需求&…

2024年12月5日Github流行趋势

项目名称&#xff1a;HelloGitHub 项目维护者&#xff1a;521xueweihan, yaowenqiang, daixiang0等项目介绍&#xff1a;分享 GitHub 上有趣、入门级的开源项目。项目star数&#xff1a;95,244项目fork数&#xff1a;9,707 项目名称&#xff1a;Best-websites-a-programmer-sh…

乾元通渠道商中标福州市人防信息化建设项目

乾元通渠道商中标福州市人防信息化建设项目&#xff0c;乾元通作为应急通讯设备厂家&#xff0c;为项目提供车载版多链路聚合通信保障设备 QYT-X1s。 青岛乾元通数码科技有限公司作为国家应急产业企业&#xff0c;深耕于数据调度算法研究&#xff0c;参与了多项国家及省部级信息…

unity3d—demo(实现给出图集名字和图片名字生成对应的图片)

目录 实现给出图集名字和图片名字生成对应的图片&#xff1a; 代码示例&#xff1a; dic: 键 是图集名称 值是一个字典 该字典键是图片名称 值是图片&#xff0c;结构如图&#xff1a; 测试代码&#xff1a; 结果&#xff1a; SpriteRenderer 讲解&#xff1a; Resour…

小型商贸公司用什么进销存软件?

最近&#xff0c;一个商贸公司的客户在了解产品时&#xff0c;向我们倾诉了自己的烦恼&#xff1a;“因为公司规模比较小&#xff0c;所以没有使用专业的进销存软件来进行管理&#xff0c;平时记录数据什么的也是使用比较简单的Excel表格。但是&#xff0c;随着业务的扩大&…

学习SqlSugar调用达梦数据库的存储过程的基本用法

将之前学习达梦数据库递归用法的SQL语句封装为存储过程&#xff0c;然后使用SqlSugar在C#程序中调用。   打开达梦管理工具&#xff0c;在SCHOOL数据库的存储过程文件夹新建存储过程&#xff0c;这里需注意&#xff0c;存储过程名称及参数名称都需要大写&#xff0c;且参数名…

记录一次老平台改造通知用户刷新页面,纯前端实现

记录一次老平台改造通知用户刷新页面&#xff0c;纯前端实现 方案概述背景现状问题本质 方案设计前提设计实现 其他补充写在最后的话抛出一个问题 方案概述 背景 前端构建完上线&#xff0c;用户还停留还在老页面&#xff0c;用户不知道网页重新部署了&#xff0c;跳转页面的时…

【WRF理论第十三期】详细介绍 Registry 的作用、结构和内容

目录 1. Introduction&#xff1a;介绍 Registry 的作用和功能。2. Registry Contents&#xff1a;详细描述 Registry 的结构和内容&#xff0c;包括各个部分的条目类型。2.1. DIMSPEC ENTRIES&#xff08;维度规格条目&#xff09;2.2. STATE ENTRIES&#xff08;状态变量条目…

微信小程序提交测试版,但是扫描体验版的二维码 显示 页面不存在

检查路径首页是否和我们微信小程序中的首页路径一致。 显然我的不一致。 {"pagePath": "pages/index/index","text": "产品","iconPath": "icons/Group 450.png","selectedIconPath": "/icons/组 …

GitToolBox插件:让IntelliJ IDEA的Git操作如虎添翼

GitToolBox插件介绍 GitToolBox是一款针对IntelliJ IDEA的插件&#xff0c;旨在增强IDE内置的Git功能&#xff0c;使Git操作更加便捷和高效。无论是单独开发者还是团队中的一员&#xff0c;这个插件都能帮助更好地管理代码和协作流程。 功能特点 分支管理&#xff1a;GitToolBo…

聚合支付系统/官方个人免签系统/三方支付系统稳定安全高并发 附教程

聚合支付系统/官方个人免签系统/三方支付系统稳定安全高并发 附教程 系统采用FastAdmin框架独立全新开发&#xff0c;安全稳定,系统支持代理、商户、码商等业务逻辑。 针对最近一些JD&#xff0c;TB等业务定制&#xff0c;子账号业务逻辑API 非常详细&#xff0c;方便内置…

Artec Leo 3D扫描仪 革新家具行业的数字化展示【沪敖3D】

随着科技的飞速进步&#xff0c;三维扫描技术已被广泛应用于包括家居行业在内的多个行业。面对现代消费者对家居产品日益增长的个性化和多样化需求&#xff0c;传统的家居设计和展示方法已难以满足市场需求。三维扫描技术的出现&#xff0c;为家居行业带来了新的发展机遇&#…