> keys pattern [? / * /[] ]
其中pattern为正则表达式,返回符合相应规则的key的列表
> exiests key
> type key
> set user:name eric
OK
set命令可以带参数,
NX:只在key不存在时,才进行赋值操作;
XX:只在key已存在时,才进行赋值操作。
mset命令用于set多个key的value
> mset user:name eric user:age 18
OK
> get user:name
"eric"
mget命令用于批量取值,参数为多个key,返回value列表
> mget user:name user:age
1) "eric"
2) "18"
> append user:name 1122
(integer) 8
> get user:name
"eric1122"
命令getrange key start end,获取开始结束索引之间的子字符串
> getrange user:name 1 6
"ric112"
strlen命令用户获取key对应的value的长度
> strlen user:name
integer) 8
> strlen user:age
(integer) 2
注意到上述创建的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支持数值操作。
incr key ,对key的value增加1
incrby key increment,增加指定的整数
> incr user:age
(integer) 19
> incrby user:age 10
(integer) 29
> get user:age
"29"
为什么说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。
Bitmap不是一个实际的数据类型,只是一系列位操作的命令,Redis将Bitmap归属于String类型。因为String最大长度为512M,所以Bitmap最多能表示232位。
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。
命令: 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。
命令: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。
命令: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的业务处理过程是单线程的,所以多个客户端的请求不会存在线程安全问题,也就不会出现商品过买的问题。
类似场景还有,统计多客户端用户访问服务端的次数,比如记录用户操作日志等业务。
假设有以下需求:电信运营商给用户提供了掌上营业厅服务,现在局方想要统计每个用户在一年内的掌上营业厅登录情况,在哪些天登录了,一共有多少天登录?
方案一:使用数据库,记录每一个用户的登录情况。用户每登录一次,则增加一条记录,记录包含登录当天的日期。然后一年中一共有多少天登录通过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有了一个基本的了解了吧。