Redis系列之数据类型String

本文详细介绍了Redis中的String数据类型,包括字符操作如设置、获取、拼接、范围提取等,数值操作如自增、自减,以及位操作如设置位、统计位1的数量等。同时还探讨了String类型与编码集的关系,以及其在Redis中的存储优化和位运算的实际应用案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis中有五种数据类型,分别是 String,List,Set,Hash,ZSet。

String类型是以字节数组的形式存储的,且存入时与客户端的编码集有关

常用操作

字符操作

  • set [key] [value] [EX seconds | PX milliseconds] [NX | XX]
    向redis中设置一对key-value
    EX seconds seconds秒后过期 | PX milliseconds milliseconds毫秒后过期
    NX 表示不存在时设置(与SETNX相同) | XX 表示存在时设置
127.0.0.1:6379> set k1 test
OK
  • get [key]
    从redis中获取指定key的值
127.0.0.1:6379> get k1
"test"
  • GETSET [key] [value]
    获取key的值并设置新值value,如果key不存在返回nil
#k1不存在
127.0.0.1:6379> GET k1
(nil)
#k1不存在,返回nil
127.0.0.1:6379> GETSET k1 aaaaa
(nil)
#上面已经设置进去了,所以获取到k1
127.0.0.1:6379> GET k1
"aaaaa"
#返回旧值,且存入新值
127.0.0.1:6379> GETSET k1 test
"aaaaa"
127.0.0.1:6379> GET k1
"test"
  • append [key] [value]
    向指定的key的值拼接字符串value
127.0.0.1:6379> APPEND k1 aaa
(integer) 7
127.0.0.1:6379> GET k1
"testaaa"
  • getrange [key] [start] [end]
    取出指定key的值的start到end下标的字符串
127.0.0.1:6379> GETRANGE k1 3 5
"taa"

Redis对字节数组既维护了正向索引,也有一个反向索引。正向从0开始,从左向右;反向从-1开始,从右向左

#-1 表示倒数第一个元素下标
127.0.0.1:6379> getrange k1 2 -1
"staaa"
#-2 表示倒数第二个元素下标
127.0.0.1:6379> getrange k1 2 -2
"staa"
  • setrange [key] [offset] [value]
    将指定的key对应值offset位置开始的字符替换为value
127.0.0.1:6379> GET k1
"testaaa"
127.0.0.1:6379> SETRANGE k1 2 bb
(integer) 7
127.0.0.1:6379> GET k1
"tebbaaa"
127.0.0.1:6379> SETRANGE k1 5 ccccc
(integer) 10
127.0.0.1:6379> GET k1
"tebbaccccc"
  • strlen [key]
    获取指定key的值的长度
127.0.0.1:6379> STRLEN k1
(integer) 7
  • SETNX [key] [value]
    当key不存在时,才设置key
#k1存在,设置失败
127.0.0.1:6379> SETNX k1 aaa
(integer) 0
127.0.0.1:6379> GET k1
"tebbaccccc"
#nx不存在,设置成功
127.0.0.1:6379> SETNX nx nxxxxx
(integer) 1
127.0.0.1:6379> GET nx
"nxxxxx"
  • SETEX [key] [second] [value]
    设置一对key-value,并且在second秒后过期
#设置k1 10秒后过期
127.0.0.1:6379> SETEX k1 10 11111
OK
127.0.0.1:6379> GET k1
"11111"
#TTL [key] 命令查看key还有多久有效期。还剩6秒过期
127.0.0.1:6379> TTL k1
(integer) 6
127.0.0.1:6379> GET k1
"11111"
#k1已过期
127.0.0.1:6379> TTL k1
(integer) -2
127.0.0.1:6379> GET k1
(nil)
为什么说与编码集有关系

分别以UTF-8、GBK编码的客户端存入"嗨"这个字,然后使用GET命令查看对应的值,再使用STRLEN查看对应的长度

  • UTF-8编码
    可以看到,"嗨"这个汉字,在UTF-8编码集下,Redis中存了一个长度为3的字节数组
127.0.0.1:6379> set k1 嗨
OK
127.0.0.1:6379> strlen k1
(integer) 3
127.0.0.1:6379> get k1
"\xe5\x97\xa8"
127.0.0.1:6379>
  • GBK编码
    可以看到,"嗨"这个汉字,在GBK编码集下,Redis中存了一个长度为2的字节数组
127.0.0.1:6379> set k1 嗨
OK
127.0.0.1:6379> STRLEN k1
(integer) 2
127.0.0.1:6379> get k1
"\xe0\xcb"

数值操作

  • INCR [key]
    对指定的key自增1
127.0.0.1:6379> SET k1 1
OK
127.0.0.1:6379> INCR k1
(integer) 2
  • INCRBY [key] [increment]
    对指定的key增加 increment的数值
127.0.0.1:6379> INCRBY k1 10
(integer) 12 
  • DECR [key]
    对指定的key减1
 DECR k1
(integer) 11
  • DECRBY [key] [decrement]
    对指定的key减少decrement的数值
127.0.0.1:6379> DECRBY k1 10
(integer) 1
  • INCRBYFLOAT [key] [increment]
    对指定的key增加increment的浮点数
127.0.0.1:6379> INCRBYFLOAT k1 0.5
"1.5"
#此时执行incr操作会报错
127.0.0.1:6379> INCR k1
(error) ERR value is not an integer or out of range
127.0.0.1:6379> INCRBYFLOAT k1 -0.5
"1"
#此时执行incr操作没有问题
127.0.0.1:6379> INCR k1
(integer) 2
#注意:INCR DECR INCRBY DECRBY操作只能对值为整数值或者对应的value可以转为整数值的key使用

Redis对数据的存储进行了优化。string类型在redis中,有三种编码形式,分别是:INT, EMBSTR,RAW。可以使用命令OBJECT ENCODING [key] 来进行查看。
当进行整型数值操作后,会将value的编码转为INT类型。方便后续的计算,而不用额外的转换判定操作

更多细节,详见 Redis编码规则

位操作bitmap

  • SETBIT [key] [offset] [value]
127.0.0.1:6379> SETBIT k1 1 1
(integer) 0
127.0.0.1:6379> get k1
"@"
#长度为1
127.0.0.1:6379> STRLEN k1
(integer) 1

在这里插入图片描述
上面的SETBIT 命令所产生的效果如上图所示,会将第一个字节的下标为1的bit位置为1,对应的十进制数值是64,对应的ASCII码就是字符’@’。

  • BITCOUNT [key] [start end]
    统计某个key的值中所有bit位中值为1的数量
    start 值的字节的起始位置
    end 值的字节的结束位置,两个不填表示所有字节
127.0.0.1:6379> SETBIT k1 1 1
(integer) 0
127.0.0.1:6379> SETBIT k1 7 1
(integer) 0
127.0.0.1:6379> setbit k1 9 1
(integer) 0
127.0.0.1:6379> get k1
"A@"
127.0.0.1:6379> BITCOUNT k1 0 0 
(integer) 2
127.0.0.1:6379> BITCOUNT k1
(integer) 3
127.0.0.1:6379> STRLEN k1
(integer) 2
127.0.0.1:6379> BITCOUNT k1 0 1
(integer) 3
  • BITPOS [key] [bit] [start end]
    查找值的bit位中第一次出现给定bit值(0或者1)的下标,这里的下标是值的所有字节的bit位的下标
    start 值的字节的起始位置
    end 值的字节的结束位置,两个不填表示所有字节
    在这里插入图片描述
    此时,k1的值的bit位如上图所示
#不填表示所有字节,因此取的是第一个字节,返回下标是1
127.0.0.1:6379> BITPOS k1 1 
(integer) 1
#取第一个字节的
127.0.0.1:6379> BITPOS k1 1 0 0
(integer) 1
#取第二个字节的
127.0.0.1:6379> BITPOS k1 1 1 1
(integer) 9
  • BITOP [operation] destkey key [key …]
    其中operation包括AND(与)、OR(或)、NOT(非)、XOR(异或)
    destkey 指的是将操作的结果存入这个key中

现在有k1和k2两个key,分别代表的是字符’A’和 ‘B’,如何操作这两个key得到字符’C’呢?

127.0.0.1:6379> get k1
"A"
127.0.0.1:6379> get k2
"B"

在这里插入图片描述
如上图所示,想要得到字符’C’,只需要对k1和k2进行或运算即可得到字符’C’了。

127.0.0.1:6379> BITOP OR k3 k1 k2
(integer) 1
127.0.0.1:6379> get k3
"C"
  1. 如果我们需要记录某个用户的一年中每天的登录情况,可以使用bitmap这种形式:
    有用户A,在1月1号登录了,2月1号登录了
    该怎么表示呢?
    1月1号 = 第1天
    2月1号 = 第32天
    12月31号 = 第365天
127.0.0.1:6379> SETBIT user::A 0 1
(integer) 0
127.0.0.1:6379> SETBIT user::A 31 1
(integer) 0
127.0.0.1:6379> SETBIT user::A 364 1
(integer) 0

查询用户一年内登录了几天

127.0.0.1:6379> BITCOUNT user::A 
(integer) 3

查询用户最后量礼拜的登录情况

#假设最后俩礼拜刚好可以用最后两个字节来表示
127.0.0.1:6379> bitcount user::A -2 -1
(integer) 1
  1. 如果我们需要统计某天有多少用户登录了,该怎么操作呢?
    假设现在有六个用户分别是用户 A B C D E F,并且可以保证他们分别映射到了bit位的0,1,2,3,4,5这六个位置上
    在10月1号,用户A和用户E登录了
127.0.0.1:6379> SETBIT 20201001 0 1
(integer) 0
127.0.0.1:6379> SETBIT 20201001 4 1
(integer) 0

10月2号,用户A B C 登录了

127.0.0.1:6379> SETBIT 20201002 0 1
(integer) 0
127.0.0.1:6379> SETBIT 20201002 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20201002 2 1
(integer) 0

10月3号,用户B D 登录了

127.0.0.1:6379> SETBIT 20201003 1 1
(integer) 0
127.0.0.1:6379> SETBIT 20201003 3 1
(integer) 0

要统计10月1号和2号这两天有几个用户登录了

127.0.0.1:6379> BITOP OR sta_0102 20201001 20201002
(integer) 1
127.0.0.1:6379> BITCOUNT sta_0102
(integer) 4

要统计10月1号到3号这三天有几个用户登录了

127.0.0.1:6379> BITCOUNT sta_010203
(integer) 5

国庆前三天,我们的用户活跃率是100%啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值