Go-Redis基础 | 青训营

105 阅读5分钟

Redis概述

Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,它可以用作数据库、缓存和消息中间件。它支持多种数据结构,包括字符串(Strings)、哈希(Hashes)、列表(Lists)、集合(Sets)、有序集合(Sorted Sets)等。Redis的设计目标是为了提供高性能、低延迟和可扩展性。

Redis本质上是一个Key-Value类型的内存数据库,很像Memcached,整个数据库加载在内存当中操作,定期通过异步操作把数据库中的数据flush到硬盘上进行保存。

优点:

  1. 快速高效: Redis是一个基于内存的数据存储系统,因此读写速度非常快,可以达到几十万甚至上百万的操作每秒。
  2. 多种数据结构: Redis支持多种数据结构,如字符串、哈希、列表、集合等,使其适用于不同的应用场景,从简单的缓存到复杂的数据处理。
  3. 持久化: Redis支持数据的持久化,可以将数据保存在磁盘上,以防止数据丢失。它支持两种持久化方式:快照(Snapshot)和日志(Append-only file)。
  4. 分布式: Redis支持分布式部署,可以通过主从复制和分片来实现数据的高可用性和扩展性。
  5. 发布订阅: Redis具有发布订阅功能,允许客户端订阅频道并接收发布到该频道的消息,用于构建实时通信和消息系统。
  6. 事务支持: Redis支持简单的事务操作,可以一次性执行多个命令,保证这些命令的原子性。
  7. 灵活性: Redis可以用于多种用途,如缓存、数据库、消息中间件等,使其在不同应用场景下都有很好的表现。

缺点:

  1. 内存限制: Redis的数据存储在内存中,因此受到可用内存的限制。虽然可以通过持久化来部分缓解这个问题,但持久化会增加写操作的开销。
  2. 单线程: Redis的主要限制是它使用单线程处理所有客户端请求。虽然通过多路复用等技术可以在实际中实现高并发,但对于某些计算密集型操作可能表现不佳。
  3. 数据一致性: Redis的主从复制虽然提供了高可用性,但在主节点故障后切换到从节点时,可能会出现数据延迟和部分数据丢失的情况。
  4. 有限查询能力: Redis主要用于键值存储,不像传统数据库那样支持复杂的查询语言。虽然有一些查询操作,但不如关系型数据库灵活。

Redis的使用场景

Redis在性能、灵活性和多功能性方面的特点使其在各种应用场景中都有应用价值。

  1. 缓存: Redis最常见的用途之一就是作为缓存层,将热门的数据存储在内存中,以加速读取操作。由于Redis的高速读写性能,它可以显著降低数据库的负载,提高应用程序的响应速度。
  2. 会话存储: Redis可以用于存储用户会话数据,特别适用于需要分布式部署的应用程序。它能够在多个应用实例之间共享会话信息,确保用户在不同请求之间的连续性。
  3. 消息中间件: Redis支持发布订阅模式,允许多个客户端订阅频道并接收发布到频道的消息。这使得Redis可以用作实时消息传递的中间件,用于构建聊天应用、通知系统等。
  4. 计数器和排行榜: Redis的原子计数操作使其非常适合用作计数器,用于实时统计和排行榜应用。例如,可以用于跟踪点赞、评论、浏览次数等。
  5. 地理位置信息: Redis的有序集合可以用于存储地理位置信息和距离计算,用于构建位置服务和附近搜索功能。
  6. 分布式锁: Redis支持原子操作,可以用来实现分布式锁,确保多个进程或实例之间的协调和同步。
  7. 数据缓存: 除了常规的缓存外,Redis还可以用来缓存计算结果、查询结果等,以减少复杂计算和查询的开销。
  8. 任务队列: Redis的列表结构可以用于构建任务队列,多个客户端可以向队列中添加任务,然后工作线程可以从队列中取出任务并执行。
  9. 临时存储: Redis适用于存储一些临时数据,如临时会话数据、临时状态信息等。
  10. 实时分析: Redis支持复杂的数据结构和操作,可以用于实时分析和数据挖掘应用,如实时统计、流量分析等。

总的来说,Redis在性能、灵活性和多功能性方面的特点使其在各种应用场景中都有应用价值。然而,在选择Redis作为解决方案时,需要根据具体的需求和应用场景来权衡其优势与局限性。

Go-Redis的基本操作

go-redis是一个基于Redigo的Redis客户端,提供了高可用性、集群支持、分片支持、发布/订阅等功能。

基本查询

	client := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379", // 你的 Redis 地址
		Password: "",              // 密码
		DB:       0,               // 数据库
	})

	// 创建上下文
	ctx := context.Background()

	// 设置键值对
	err := client.Set(ctx, "mykey", "Hello, Redis!", 0).Err()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 获取值
	val, err := client.Get(ctx, "mykey").Result()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Value:", val)

基本数据操作

// 操作列表
	client.RPush(ctx, "mylist", "item1")
	client.RPush(ctx, "mylist", "item2")
	client.RPush(ctx, "mylist", "item3")

	listVals, err := client.LRange(ctx, "mylist", 0, -1).Result()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("List values:", listVals)

	// 操作集合
	client.SAdd(ctx, "myset", "member1")
	client.SAdd(ctx, "myset", "member2")
	client.SAdd(ctx, "myset", "member3")

	setMembers, err := client.SMembers(ctx, "myset").Result()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Set members:", setMembers)

	// 操作哈希
	client.HSet(ctx, "myhash", "field1", "value1")
	client.HSet(ctx, "myhash", "field2", "value2")

	hashVals, err := client.HGetAll(ctx, "myhash").Result()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	fmt.Println("Hash values:", hashVals)

	// 设置过期时间
	client.Set(ctx, "expirekey", "I will expire", 10*time.Second)

	// 等待过期
	time.Sleep(12 * time.Second)
	val, err = client.Get(ctx, "expirekey").Result()
	if err == redis.Nil {
		fmt.Println("Key not found")
	} else if err != nil {
		fmt.Println("Error:", err)
	} else {
		fmt.Println("Value after expiration:", val)
	}