API的理解和使用——字符串的命令
命令 | 作用 |
set | |
setex | |
setnx | |
get | |
mset | |
mget | |
incr | |
decs | |
incrby | |
decrby | |
incrbyfloat | |
append | |
strlen | |
getset | |
setrange | |
getrange |
字符串类型是Redis最基础的数据结构。首先键都是字符串类型。
而且其他几种数据结构都是在字符串类型基础上构建的,所以字符串类型能为其他四种数据结构的学习奠定基础。
字符串类型的值可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数)、
甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。
字符串类型的命令比较多,我们将其分为常用的和不常用的两类。
1.字符串常用命令
1)设置值
命令:set key value [ex seconds] [px milliseconds] [nx|xx]
set命令的可选参数:
ex seconds:为键设置秒级过期时间。
px milliseconds:为键设置毫秒级过期时间。
nx:键必须不存在,才可以设置成功,用于添加。
xx:与nx相反,键必须存在,才可以设置成功,用于更新。
127.0.0.1:6379> set name kebi OK 127.0.0.1:6379> set name kebi ex 20 xx OK 127.0.0.1:6379> set age 26 nx OK
除了set,Redis还提供了setex和setnx两个命令
语法:
setex key seconds value
setnx key values
setex和setnx可以看作set的专业定制版,适合某些场合。
ex是用来设置时间的,所以后面必须接时间。
nx是键必须不存在,所以不能用来更新。
127.0.0.1:6379> set age 26 nx OK 127.0.0.1:6379> setnx age 26 (integer) 0 #设置失败,setnx必须设置不存在的 127.0.0.1:6379> set age 27 OK #可以更新 127.0.0.1:6379> setex name 30 kebi OK #可以更新
setnx和setex有什么用了?
以setnx命令为例,由于Redis的单线程命令处理机制,如果有多个客户端同时执行setnx key value,
根据setnx的特性只有一个客户能设置成功,setnx可以作为一种分布式锁的一种实现方案。
2)获取值
命令:get key
127.0.0.1:6379> get age "27" 127.0.0.1:6379> get age_kebi (nil)
如果要获取的键不存在,则返回nil(空)。
3)批量设置值
命令:mset key value [key value...]
下面操作通过mset命令一次性设置4个键值对:
127.0.0.1:6379> mset a 1 b 2 c 3 d 4 OK
4)批量获取值
命令:mget [key...]
下面操作批量获取4个键的值:
127.0.0.1:6379> mget a b c d 1) "1" 2) "2" 3) "3" 4) "4"
如果有些键不存在,那么它的值为nil(空),结果是按照传入键的顺序返回:
127.0.0.1:6379> mget a b c f 1) "1" 2) "2" 3) "3" 4) (nil)
批量操作命令可以有效提高开发效率,假如没有mget这样的命令,要执行n次get命令需要按照如下方式来执行:
具体耗时:n次get时间 = n次网络时间 + n次命令时间
使用mget命令后,要执行n次get命令操作只需要按照如下方式即可:
具体耗时:n次get时间 = 1次网络时间 + n次命令时间
Redis可以支撑每秒数万的读写操作,但是这指的是Redis服务端的处理能力,
对于客户端来说,一次命令除了命令时间还有网络时间,假设网络时间为1毫秒,命令时间为0.1毫秒,
按照每秒处理一万次命令算,那么执行1000次get命令和一次mget命令的区别在于:
操作 | 时间 |
1000次get | 1000 x 1 + 1000 x 0.1 = 1100毫秒 = 1.1秒 |
1次mget(组装了1000个键值对) | 1 x 1 + 1000 x 0.1 = 101毫秒 = 0.101秒 |
因为Redis的处理能力已经足够高,对于开发人员来说,网络可能成为性能的瓶颈。
学会使用批量操作,有助于提高业务处理效率,但是要注意的是每次批量操作所发送的命令不是无节制的,
如果数量过多可能造成Redis阻塞或者网络阻塞。
5)计数
命令:incr key
incr命令用于对值做自增操作,返回结果分为三种情况:
(1)值不是整数,返回错误。
(2)值是整数,返回自增后的结果。
(3)键不存在,按照值为0自增,返回结果是1.
#值不是整数 127.0.0.1:6379> set name kebi OK 127.0.0.1:6379> incr name (error) ERR value is not an integer or out of range #报错 #值是整数 127.0.0.1:6379> set age 25 OK 127.0.0.1:6379> incr age (integer) 26 #加1返回结果 127.0.0.1:6379> incr age (integer) 27 #值不存在,返回1 127.0.0.1:6379> exists sex (integer) 0 127.0.0.1:6379> incr sex (integer) 1
除了incr命令,Redis提供了decr(自减)、incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数):
语法:
decr key
incrby key increment
decrby key decrement
incrbyfloat key increment
#值为整数 127.0.0.1:6379> incr sex (integer) 7 127.0.0.1:6379> decr sex (integer) 6 127.0.0.1:6379> decr sex (integer) 5 127.0.0.1:6379> exists a (integer) 1 127.0.0.1:6379> decr a (integer) 0 127.0.0.1:6379> decr a #可以返回负数 (integer) -1 127.0.0.1:6379> decr a (integer) -2 127.0.0.1:6379> decr name #不是整数报错 (error) ERR value is not an integer or out of range
#值不存在 127.0.0.1:6379> exists g (integer) 0 127.0.0.1:6379> incrby g 3 (integer) 3 127.0.0.1:6379> incrby g 3 (integer) 6 #值不是整数 127.0.0.1:6379> incrby name (error) ERR wrong number of arguments for 'incrby' command #值是整数 127.0.0.1:6379> decr age (integer) 26 127.0.0.1:6379> incrby age 2 (integer) 28 127.0.0.1:6379> incrby age 2 (integer) 30
#值不存在 127.0.0.1:6379> exists h (integer) 0 127.0.0.1:6379> decrby h 2 (integer) -2 #值不是整数 127.0.0.1:6379> decrby name (error) ERR wrong number of arguments for 'decrby' command #值为整数 127.0.0.1:6379> decrby age 3 (integer) 27 127.0.0.1:6379> decrby age 3 (integer) 24
#值不是整数 127.0.0.1:6379> incrbyfloat name 1.5 (error) ERR value is not a valid float #值是整数 127.0.0.1:6379> incrbyfloat age 2.5 "28.5" #值不存在 127.0.0.1:6379> incrbyfloat y 2.5 "2.5"
注意:上面这些不同的类型指的增减数字的类型,例如是每次加1还是1.5
很多存储系统和编程语言内部都使用CAS机制实现技术功能,会有一定的CPU开销,但是在Redis中完全不存在这个问题
因为Redis是单线程架构,任何命令到了Redis服务端都要顺序执行。
2.字符串不常用命令
1)追加值
命令:append key value
append可以向字符串尾部追加值:
127.0.0.1:6379> get name "kebi" 127.0.0.1:6379> append name goods #追加 (integer) 9 #返回这个值的长度 127.0.0.1:6379> get name "kebigoods"
2)字符串长度
命令:strlen key
127.0.0.1:6379> get name "kebigoods" #一个字母一个字节 127.0.0.1:6379> strlen name (integer) 9
如果字符串是汉字,一个汉字占3个字节:
127.0.0.1:6379> set name:chinese "科比" OK 127.0.0.1:6379> strlen name:chinese (integer) 6
3)设置并返回原值
命令:get key value
getset和set一样能设置值,但不同的是,它会返回原值:
127.0.0.1:6379> getset name kebi-bryant "kebigoods" 127.0.0.1:6379> getset class seven (nil) #原值不存在返回空
4)设置指定位置的字符
命令:setrange key offeset values
127.0.0.1:6379> set drom 301 OK 127.0.0.1:6379> setrange drom 3 B #替换掉指定位置的字符,可以加 (integer) 4 127.0.0.1:6379> get drom "301B" #注意外国人计数从0开始 #替换之后中间有空格,用十六进制补 127.0.0.1:6379> set drom 301 OK 127.0.0.1:6379> setrange drom 4 B (integer) 5 127.0.0.1:6379> get redis (nil) 127.0.0.1:6379> get drom "301\x00B"
5)获取部分字符串
命令:getrange key start end
start和end分别是开始和结束的偏移量,偏移量从0开始计算
127.0.0.1:6379> get name "kebi-bryant" 127.0.0.1:6379> getrange name 0 3 "kebi"
最后提供一张字符串类型命令的时间复杂度,之前讲dbsize命令时提到过,可以作为参考依据。结合自身业务需求和数据大小选择适合的命令。
命令 | 时间复杂度 |
set key value | O(1) |
get key | O(1) |
del key [key ...] | O(k),k是键的个数 |
mset key value [key value ...] | O(k),k是键的个数 |
mget key [key...] | O(k),k是键的个数 |
incr key | O(1) |
decr key | O(1) |
decrby key decrement | O(1) |
incrby key increment | O(1) |
incrbyfloat key increment | O(1) |
append key value | O(1) |
strlen key | O(1) |
setrange key offset value | O(1) |
getrange key start end |
O(n),n是字符串长度,由于获取字符串非常快 所以,字符串不是很长,可以视同为O(1) |