Redis基本数据类型之String

Redis中的Key

  • Redis中的key是二进制安全的,可以使用任意二进制序列作为key,即如字符串或者图片的内容都可以作为key,注意:空字符串在Redis中也被认为是有效的key。
  • key不宜过长,一是从存储角度来讲比较耗费内存,而且在查找key时对key进行比较将会增加开销。
  • 推荐使用中划线或冒号将描述字段分隔,整体作为key,如:“student:id”、“student:age”。
  • key的最大容量为512M

基本命令

  1. 获得一个符合匹配规则的键名列表
> keys pattern [? / * /[] ]

其中pattern为正则表达式,返回符合相应规则的key的列表

  1. 判断一个键是否存在
> exiests key
  1. 获取key所对应的value的数据结构类型
> type key

基本数据类型-String

1. 基本赋值、取值操作

1.1 赋值

> set user:name eric
OK

set命令可以带参数,
NX:只在key不存在时,才进行赋值操作;
XX:只在key已存在时,才进行赋值操作。

1.2 批量赋值

mset命令用于set多个key的value

> mset user:name eric user:age 18
OK

1.3 取值

> get user:name
"eric"

1.4 批量取值

mget命令用于批量取值,参数为多个key,返回value列表

> mget user:name user:age
1) "eric"
2) "18"

2. 字符串操作

2.1 字符串拼接

> append user:name 1122
(integer) 8
> get user:name 
"eric1122"

2.2 字符串截取

命令getrange key start end,获取开始结束索引之间的子字符串

> getrange user:name 1 6
"ric112"

2.3 获取长度

strlen命令用户获取key对应的value的长度

> strlen user:name
integer) 8 
> strlen user:age
(integer) 2

3. 数值操作

注意到上述创建的key中的value的类型是相同的,都是string,如下:

> type user:name
string
> type user:age
string

但是使用OBJECT ENCODING命令进一步查看value的编码类型:

> object encoding user:name
"raw"
> object encoding user:age
"int"

string类型针对以int为编码格式的value支持数值操作。

3.1 增加

incr key ,对key的value增加1
incrby key increment,增加指定的整数

> incr user:age
(integer) 19
> incrby user:age 10
(integer) 29
> get user:age
"29"

3.2 减少(与加类似)

3.3 二进制安全

为什么说Redis是二进制安全的?我们先来看下面的例子:

> set num 99
OK
> strlen num
(integer) 2

此时,如果将num自增1,再使用strlen来获取num的长度,结果会是什么呢?

> incr num
(integer) 100
> strlen num
???

此时num的value为100,那么此时获取这个value的长度,结果是多少呢?
答案是:3

如果把num加1000呢?此时value的长度是多少?

> incrby num 1000
(integer) 1100
> get num 
"1100"
> strlen num
???

num的value是1100,编码类型为int,那么长度是多少?java中整型长度为4个字节,Redis中是怎样的?1100由几个字节能够表示?

程序运行的答案是:4
为什么?
因为Redis是二进制安全的,所谓二进制安全就是指传输给我的数据的二进制是什么样,我就按什么样保存,不会对数据进行再编码、序列化等操作。本质上数据都以字节数组的形式存储与获取,这也就意味着不会有溢出或者乱码问题。
所以“100”这个字符串的长度为3,“1100”的长度就是4。

4.Bitmap

Bitmap不是一个实际的数据类型,只是一系列位操作的命令,Redis将Bitmap归属于String类型。因为String最大长度为512M,所以Bitmap最多能表示232位。

4.1 赋值与取值

setbit和getbit命令用来设置/获取二进制的具体某位的值,命令格式如下:
setbit/getbit key [offset value]
其中offset为二进制的具体位数,value是将该位置为1或0。

> setbit key 1 1
(integer) 1
> getbit key 1 
(integer) 1
> get key 
"@"
> strlen key
(integer) 1

上述setbit命令将一个字节的第1位赋值为1,此时key对应的value为01000000,getbit命令获取该二进制数的第1位,为1;01000000对应的ASSIC码为“@”,即value为“@”。

此时,执行以下命令:

> setbit key 9 1
(integer) 0
> strlen key
(integer) 2

将第9位置为1,Redis会自动向后补一个字节,变为两个字节(即01000000 01000000),value的第9位即第二个字节的第1位被置为1。故现在value的长度为2。

4.2 Bit位统计

命令: bitcount key [start end]用来统计value中有多少位为“1”;
其中start代表开始字节的索引值,end代表结束字节的索引值(注意此处为字节的索引,而不是二进制位的索引)。
如下:

#此时key的值为 01000000 01000000
> bitcount key 0 1
(integer) 2
> bitcount key 1 1
(integer) 1

第一条命令从第0个字节开始到第1个字节结束,统计“1”的个数,结果为2;
第二条命令其实就是统计第1个字节中“1”的个数,所以结果为1。

4.3 Bit位查找

命令:bitpos key bit [start end]用来查找指定字节范围中第一个bit位的索引;
其中,bit为需要查找的值可为0或1,start、end分别代表查找范围中的开始、结束字节的索引。
如下:

#key的值为 01000000 01000000
> bitpos key 1 1 1
(integer) 9
> bitpos key 1 0 1
(integer) 1

第1个字节中第一个“1”的位索引为9,第0个到第1个字节范围内第一个“1”的位索引为1。

4.4 Bit位操作

命令:bitop operation destkey key [key …]

#创建k1,将第1位和第7位分别置为1,即01000001,即字符“A”
> setbit k1 1 1
(integer) 0
> setbit k1 7 1
(integer) 0
> get k1
"A"
#创建k2,将第1位和第6位分别置为1,即01000010,即字符“B”
> setbit k2 1 1
(integer) 0
> setbit k2 6 1
(integer) 0
> get k2
"B" 

(1)与操作–and

#将k1和k2相与,结果应为:01000000,即字符“@”,结果保存至destkey
> bitop and andkey k1 k2
(integer) 1
> get andkey 
"@"

(2)或操作–or

#将k1和k2相与,结果应为:01000011,即字符“C”,结果保存至destkey
> bitop or orkey k1 k2
(integer) 1
> get orkey 
"C"

简单应用场景

Redis针对数据提供了上述的各种运算方法,客户端进行处理时,直接调用Redis的数据处理方法即可,同时数据又是存储在Redis内部的,这种行为被称为“计算向数据移动”。

数值计算操作应用场景

一个典型的场景就是秒杀,用户通过访多个客户端进行商品秒杀,可以抽象为:客户端通过Redis进行数值的自增,增加到商品的最大数量时,秒杀结束。
因为Redis的业务处理过程是单线程的,所以多个客户端的请求不会存在线程安全问题,也就不会出现商品过买的问题。
类似场景还有,统计多客户端用户访问服务端的次数,比如记录用户操作日志等业务。

Bitmap应用场景

假设有以下需求:电信运营商给用户提供了掌上营业厅服务,现在局方想要统计每个用户在一年内的掌上营业厅登录情况,在哪些天登录了,一共有多少天登录?
方案一:使用数据库,记录每一个用户的登录情况。用户每登录一次,则增加一条记录,记录包含登录当天的日期。然后一年中一共有多少天登录通过SQL语句来查询。
问题:一个用户在一年中有多少天登录,就会产生多少条记录,这里还要注意到电信运营商的用户数基本是千万级的,这样这张表就会变的庞大无比,本方案不可行。
方案二:使用Redis的Bitmap来存储用户登录信息

#用户eric分别在第2天、第4天和第365天登录了系统,将登录信息存储到Bitmap中
> setbit eric 1 1
(integer) 0

> setbit eric 3 1
(integer) 0

> setbit eric 364 1
(integer) 0

此时用于存储用户eric登录信息的数据大小为:

> strlen eric
(integer) 46

46字节
每个用户使用46个字节就可以统计其一年的登录情况,与数据库的方案相比,更具有可行性。
获取用户登录情况:

# Redis提供了双向索引,-1代表最后一个元素
> bitcount eric 0 -1
(integer) 3

当然,实际场景下如果确实有千万级以上的活跃用户,系统压力也还是很大的,这里的例子仅仅是对方案一数据库存储进行优化。

小结

本文大致介绍了Redis中key的概念和几个关于key的命令,然后着重介绍了Redis基本数据类型中的String,分为字符串、数值、和Bitmap。分别列举了针对各数据类型的处理命令,突出了计算向数据移动的特点。最后还介绍了几个实用场景,经过本次介绍,想必大家对Redis的String有了一个基本的了解了吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章