Redis常用数据结构

Redis数据结构简述
数据结构底层的数据结构

1.String(基于SDS)

应用场景:缓存对象、常规计数、分布式锁、共享 session 信息等。

简单动态字符串(SDS)与原生字符串的区别:

  • SDS 不仅可以保存文本数据,还可以保存二进制数据。因为SDS 使用 len 属性的值而不是空字符来判断字符串是否结束,并且 SDS 的所有 API 都会以处理二进制的方式来处理 SDS 存放在 buf[] 数组里的数据;
  • Redis 的 SDS API 是安全的,拼接字符串不会造成缓冲区溢出。 SDS 在拼接字符串之前会检查 SDS 空间是否满足要求,如果空间不够会自动扩容;
  • 取字符串长度的时间复杂度是 O(1)。
    String结构

1.1 String的三种编码格式

String存储的值对象
在这里插入图片描述

完整
embstr和raw编码都会使用SDS来保存值,但不同之处在于embstr会通过一次内存分配函数来分配一块连续的内存空间来保存redisObject和SDS,而raw编码会通过调用两次内存分配函数来分别分配两块空间来保存redisObject和SDS。

1.2 基本使用

127.0.0.1:6379> set name dx
OK
127.0.0.1:6379> get name
"dx"
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> strlen name
(integer) 2
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)

1.3 存储webp格式的文件

var rdb *redis.Client
func initClient() (err error) {
	rdb = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // 密码
		DB:       0,  // 数据库
		PoolSize: 20, // 连接池大小
	})

	_, err = rdb.Ping().Result()
	return err
}
// 缓存图片
func CachePicWithRedis() {
	// 打开图片文件
	data, err := os.ReadFile("D:/Projects/go_-projects/gin_test/redisdemo/img.webp")
	if err != nil {
		panic(err)
	}

	// 将图片数据写入Redis
	err = rdb.Set("image", data, 0).Err()
	if err != nil {
		panic(err)
	}

	fmt.Println("Image cached in Redis.")
}
func RedisDemo() {
	err := initClient()
	if err != nil {
		fmt.Printf("redis init failed, err:%v\n", err)
		return
	}
	fmt.Printf("redis init success...\n")
	defer rdb.Close()
	CachePicWithRedis()
}

执行

127.0.0.1:6379> get image

后的部分结果

...4\xd7BM\xe4cK\xc3\xb3\x969\xe2\x01\x95\x9c\xb6EVI\xb31\xc7\xa3\xaa\x02DN\xff\xef\xfe<\x91\x029k\b\xcd\x0e:\x061\x8f}\xd1_\x19\xbb\x82\x84.\x05\xb3\xb1\n\xc0KU/\x85\x00\x83\x01$\xb3.\x99\xcc\xa0\x13>W\xc0\x84\xed,^\t\x02\xc9=t\x0c\x90\x80\xf5\xe6\x94M\x91\x03,y\x8a\x8d\xdb\x1a\xaeB\xb6\xf8\xd2Fg\...

1.4 应用

1.4.1缓存对象(见1.2和1.3)
1.4.2常规计数
127.0.0.1:6379> SET aritcle:readcount:1001 0
OK
127.0.0.1:6379> INCR aritcle:readcount:1001
(integer) 1
127.0.0.1:6379> INCR aritcle:readcount:1001
(integer) 2
127.0.0.1:6379> DECR aritcle:readcount:1001
(integer) 1
127.0.0.1:6379> GET aritcle:readcount:1001
"1"
1.4.3分布式锁

实现原理:SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁,如果 key 不存在,则显示插入成功,可以用来表示加锁成功;如果 key 存在,则会显示插入失败,可以用来表示加锁失败。

设置锁

//unique_value用于标识加锁的客户端,只有加锁的客户端才能解锁;
//NX代表只在 lock_key 不存在时,才对 lock_key 进行设置操作;
//PX 10000 表示设置 lock_key 的过期时间为 1000s,这是为了避免客户端发生异常而无法释放锁。
127.0.0.1:6379> SET lock_key unique_value NX PX 1000000 
OK

解锁时,先获取值,判断值与当前解锁的客户端是否一致,一致就删除key,解锁成功,否则解锁失败。

1.4.4共享session信息

通常我们在开发后台管理系统时,会使用 Session 来保存用户的会话(登录)状态,这些 Session 信息会被保存在服务器端,但这只适用于单系统应用,如果是分布式系统此模式将不再适用。
例如用户一的 Session 信息被存储在服务器一,但第二次访问时用户一被分配到服务器二,这个时候服务器并没有用户一的 Session 信息,就会出现需要重复登录的问题,问题在于分布式系统每次会把请求随机分配到不同的服务器。
因此,我们需要借助 Redis 对这些 Session 信息进行统一的存储和管理,这样无论请求发送到那台服务器,服务器都会去同一个 Redis 获取相关的 Session 信息,这样就解决了分布式系统下 Session 存储的问题。
Redis共享Session信息

List(基于quicklist)

应用场景:消息队列(但是有两个问题:1. 生产者需要自行实现全局唯一 ID;2. 不能以消费组形式消费数据)等。

注:5.0 版新增Stream,用于做消息队列,相比于基于 List 类型实现的消息队列,可以自动生成全局唯一消息ID,支持以消费组形式消费数据。

Hash(Redis7基于listpack)

应用场景:缓存对象、购物车等。

Set(哈希表或整数集合)

应用场景:聚合计算(并集、交集、差集)场景,比如点赞、共同关注、抽奖活动等。

ZSet(Redis7基于listpack)

应用场景:排序场景,比如排行榜、电话和姓名排序等。

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值