title: 字符串string
categories:
- C++ Backend
- Redis
- Redis command
- Data structure
tags:
- Redis
date: 2025-04-03 00:00:00
cover: /images/Redis.png

string

string类型

Redis中的字符串,直接就是按照二进制数据方式进行存储的!(不会进行任何的编码转换,存的是啥,取出来的就是啥)。Redis对于string类型,限制了大小最大是512Mredis单线程模型,希望进行的操作都能比较迅速。

可以存储文本数据,整数、普通字符串、JSON、XML、二进制数据(图片,视频、音频)

相关命令

append

APPEND KEY VALUE:字符串追加字符串
127.0.0.1:6379> set key1 "123"
OK
127.0.0.1:6379> append key1 你好
(integer) 9
127.0.0.1:6379> get key1
"123\xe4\xbd\xa0\xe5\xa5\xbd"

xshell中断,默认字符编码都是UTF-8,在中断中输入汉字之后,也是按照UTF8编码的,一个汉字在UTF-8字符集中,通常是3个字符。

getrange

功能:返回key对应的闭区间[start, end]value字符串。start和end也可以为负数-1

GETRANGE key range start end

127.0.0.1:6379> set key hwlloworld
OK
127.0.0.1:6379> getrange key 0 -1
"hwlloworld"
127.0.0.1:6379> getrange key 1 -2
"wlloworl"
127.0.0.1:6379> set key1 你好
OK
127.0.0.1:6379> getrange key1 0 -1
"\xe4\xbd\xa0\xe5\xa5\xbd"
127.0.0.1:6379> getrange key1 0 -2
"\xe4\xbd\xa0\xe5\xa5"

setrange

功能:覆盖字符串的一部分,从指定的偏移开始。z
注意:插入中文会导致乱码!

SETRANGE key offset value

127.0.0.1:6379> set key helloworld
OK
127.0.0.1:6379> setrange key 1 aaa
(integer) 10
127.0.0.1:6379> get key
"haaaoworld"

当我们向不存在的key中加字符串时,会凭空生成一个0x00字节。将value插到这个0x00后面了。

127.0.0.1:6379> setrange key2 1 aaa
(integer) 4
127.0.0.1:6379> get key2
"\x00aaa"

strlen

获取key对应的string的长度。当key存放的类似不是string时,报错。

时间复杂度:$O(1)$

STRLEN key

127.0.0.1:6379> set key "hello world!"
OK
127.0.0.1:6379> strlen key
(integer) 12

内部编码

字符串类型的内部编码有3中:

  1. int:8个字节的长整型
  2. embstr:小于等于39个字节的字符串
  3. raw:大于39个字节的字符串
127.0.0.1:6379> object encoding key
"int"
127.0.0.1:6379> set key2 hello
OK
127.0.0.1:6379> object encoding key2
"embstr"
127.0.0.1:6379> set key3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OK
127.0.0.1:6379> object encoding key3
"raw"

对于某个业务场景,有很多很多的key,类型都是string,但是每个value的string长度都是100左右。字符串使用embstr来存储也不是不能考虑。

上述效果具体怎么实现?

  1. 先看redis是否提供了对应的配置项,可以修改39这个数字。
  2. 如果没有提供配置型,就需要针对redis源码进行魔改。

Redis会根据当前值的类型和长度动态决定存储值的类型。

127.0.0.1:6379> set key4 1.4
OK
127.0.0.1:6379> object encoding key4
"embstr"

redis存储小数,本质上还是当做字符串来存储,这就和整数相比差别就很大了。小数都是使用字符串来存,意味着每次进行算术运算,都需要把字符串转换为小数,进行运算,结果再转回字符串来保存。

应用场景

缓存(Cache)功能

图中是比较典型的缓存实用场景,其中Redis作为缓冲层,MySQL作为存储层,绝大部分请求都是从Redis中获取。由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。

alt text{: height=75%, width=75%}

整体思路:
应用服务器访问数据的时候,先查询Redis

上述策略存在一个明显的问题:
随着时间的推移,肯定会有越来越多的keyredis上访问不到。从而从MySQL读取并写入Redis了。此时redis中数据就会越来越多。

  1. 把数据写给redis的同时,给key设置一个过期时间。
  2. Redis也存在内存不足的时候,提供了淘汰策略。

计数(Count)功能

很多应用都会使用Redis作为技术工具的计数工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理货值落地到其他数据元源。例如视频网站播放次数可以使用Redis完成:用户每播放一次视频,相应的视频播放就会自增1

alt text{: height=75%, width=75%}

Session会话

一个分布式Web服务器将用户的Session信息(例如用户的登录信息)保存在各自的服务器中,但这样会造成一个问题:出于负载均衡的考虑,分布式服务会将用户的访问请求均衡到不同的服务器上,并且通常无法保证用户每次请求都会被均衡到同一台服务器上,这样当用户刷新一次访问可能发现需要重新登录,这个问题是用户无法容忍的。

alt text

我们可以使用redis,把所有的会话统一放到redis里面。任何服务器要想访问seesion就要先访问seesion。

alt text

手机验证码

很多应用出于安全考虑,会在每次登录时,让用户输入手机号并且配合给手机发送验证码,然后让用户再次输入收到的验证码并进行验证,从而确定是否是用户本人。为了短信接口不会频繁访问,会限制用户每分钟获取验证码的频率:例如一分钟不能成功5次。

alt text

  1. 生成验证码:用户输入一下手机号,点击获取验证码
  2. 检查验证码:把短信收到的验证码这一串数,提交到系统中,系统验证进行验证码是否正确

总结

命令 执行效果 时间复杂度
set key value 设置key的值 O(1)
del key [key...] 删除指定的key O(k)
meset key value [key value...] 批量设置指定的key和value O(k)
mget key [key...] 批量获取key的值 O(k)
incr key 指定的key的值+1 O(1)
decr key 指定的key的值-1 O(1)
incrby key n 指定的key的值+n O(1)
decrby key -n 指定的key的值-n O(1)
incrbyfloat key n 指定的key的值-n O(1)
append key value 指定的key的值追加value O(1)
strlen key 获取指定key的长度 O(1)
setrange key offset value 覆盖指定的key的从offset开始的部分值 O(n)
getrange key start end 获取指定key的从start到end的部分值 O(n)