文章目录
字符串命令存值相关(set)取值相关(get) 数值操作命令加操作减操作 BIT位操作命令应用场景字符串命令
存值相关(set)
set key value
例如 set age 17,即将age的值设置为17。如果 key 已经存储其他值, set就覆写旧值,且无视类型,在将set age 17之后,我们再执行set age 18 这时候age的值就变为了18,因为再redis里面key相当于一个主键,具有唯一性。
在2.6.12版本,SET命令加上了一些参数:
用法:
SET key value [EX seconds][PX milliseconds][NX|XX]
EX seconds : 设置键key的过期时间,单位时秒
PX milliseconds : 设置键key的过期时间,单位时毫秒
NX : 只有键key不存在的时候才会设置key的值
XX : 只有键key存在的时候才会设置key的值
加上这参数之后,SET命令已经取代了SETNX、SETEX、PSETEX这三个命令,因此,Redis不再推荐使用这些命令,并且有可能在未来 版本中抛弃这些命令。
getset key value
用于设置指定 key 的值,并返回 key 的旧值。key 无旧值时返回 nil ,如果key存在,但是保存的数据不是字符串则会报错。
127.0.0.1:6379> getset age 20"18"
mset key1 value1 key2 value2 ...
用于同时设置一个或多个 key-value,如果已经存在,则覆盖旧值。MSET命令是原子操作,并且不会失败。
127.0.0.1:6379> mset name lisi age 18OK127.0.0.1:6379> mget name age1) "lisi"2) "18"
setrange key offset value
用指定的字符串覆盖给定 key 所储存的字符串值,覆盖的位置从偏移量 offset 开始,如果offset超出value的长度,则会为string补0。返回被修改后的字符串长度
127.0.0.1:6379> setrange age 0 20(integer) 2127.0.0.1:6379> get age"20"//如下补0操作127.0.0.1:6379> setrange name 5 lisi(integer) 9127.0.0.1:6379> get name"lisi\x00lisi"
setex key seconds value
将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。 如果 key 已经存在, SETEX 命令将覆写旧值。
127.0.0.1:6379> setex name 30 zhangsanOK127.0.0.1:6379> get name"zhangsan"127.0.0.1:6379> ttl name(integer) 28127.0.0.1:6379> ttl name(integer) 11127.0.0.1:6379> ttl name(integer) 5127.0.0.1:6379> ttl name(integer) 2127.0.0.1:6379> ttl name(integer) 0127.0.0.1:6379> ttl name(integer) -2127.0.0.1:6379> get name(nil)
setnx key value
setnx是"SET if Not Exist"的缩写,在指定的 key 不存在时,为 key 设置指定的值,存在key设置返回0,成功返回1 失败返回0
127.0.0.1:6379> setnx name zhangsan(integer) 1127.0.0.1:6379> setnx name lisi(integer) 0
psetex key millisecond value
该命令类似于SETEX,唯一不同的时,该命令设置过期时间以毫秒为单位。以毫秒为单位设置 key 的生存时间 成功时返回 OK
Msetnx key1 value1 key2 value2 …
设置一个或多个 key-value ,如果有一个key已经存在,则所有的key都会设置不成功。返回1表示所有的key都已经设置成功,返回0表示所有的key都没有设置成功。
append key value
用于为指定的 key 追加值,
如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。
如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样。
取值相关(get)
get key
get可以通过key值获取到相应的value,例如 get age,key 不存在返回 nil 。如果key 储存的值不是字符串类型,返回一个错误
127.0.0.1:6379> set age 18OK127.0.0.1:6379> get age"18"
getrange key start end
返回指定的key的指定范围(包含start和end)的子串。start和end同样也可以是负数
,这点可以参考BITPOS命令。
为什么可以是负数?
这里要知道
反向索引
的概念:正向索引,0代表第一位
反向索引,-1表示倒数第一位,-2表示倒数第二位,以此类推
127.0.0.1:6379> set name zhangsanOK127.0.0.1:6379> getrange name 0 4"zhang"127.0.0.1:6379> getrange name -3 -1"san"
mget key1 key2 ...
返回所有给定的一个或多个key 的值。 如果给定的 key 里面某个 key 不存在,那么这个 key 返回nil 。
127.0.0.1:6379> mget name age1) "zhangsan"2) "20"
strlen key
返回指定key存储的value的长度,如果value不是字符串,则会报错。如果key不存在,则返回0。
127.0.0.1:6379> get name"zhangsan"127.0.0.1:6379> strlen name(integer) 8
注意,这里的长度是值value值的字节长度,而不是字符长度,如下,中文utf-8占3个字节
127.0.0.1:6379> set name 张OK127.0.0.1:6379> get name"\xe5\xbc\xa0"127.0.0.1:6379> strlen name(integer) 3
数值操作命令
加操作
incr key
将 key 中储存的数值加1 ,
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作,
如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
执行此操作时,字符串被解析为10进制的64位有符号整数。由于Redis内部有整数形式(integer representation)来保存整数,因此不会有整数存储为字符串的额外开销。
127.0.0.1:6379> get age"20"127.0.0.1:6379> incr age(integer) 21127.0.0.1:6379> incr age(integer) 22127.0.0.1:6379> incr age(integer) 23
incrby key increment
将 key 中储存的数值加上指定的增量值,和incr 一样,只是指定了要加的数值 。
127.0.0.1:6379> incr age(integer) 24127.0.0.1:6379> incrby age 3(integer) 27
incrbyfloat key increment
为 key 中所储存的值加上指定的浮点数增量值,
该命令会把字符串解析为浮点数,然后加上指定的浮点数。如果value不是字符串类型或者不能解析为浮点数,则会报错。返回值的精度为小数点后17位。其内部以科学计数法的形式存储。
127.0.0.1:6379> get age"27"127.0.0.1:6379> incrbyfloat age 0.5"27.5"
减操作
decr key
将 key 中储存的数值减1,作数最大为64位有符号整数,
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作,
如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
127.0.0.1:6379> get age"27"127.0.0.1:6379> decr age(integer) 26127.0.0.1:6379> decr age(integer) 25
decrby key increment
将 key 所储存的值减去指定的减量值
127.0.0.1:6379> get age"23"127.0.0.1:6379> decrby age 3(integer) 20
BIT位操作命令
注意:在redis中,存储的字符串都是以二进制的形式存在的。比如:设置一个key-value,键的名字叫“a” ,值为字符’a’,‘a’ 的ASCII码是97。转换为二进制是:01100001。
setbit key offset value
设置指定位置的bit值。当key不存在时,会先生成一个字符串,这个字符串必须保证offset处有值。
offset的学名叫做“偏移” ,二进制中的每一位就是offset值,比如’a’,转换为二进制是:01100001,在这里offset 0 等于 ‘0’ ,offset 1等于’1’ ,offset2等于’1’,offset 6 等于’1’ ,没错,offset是从左往右计数的,也就是从高位往低位。
那如何通过SETBIT命令将 键a的值 ‘a’ 变成 ‘b’ 呢?就是将 01100001 加1变成 01100010(b的ASCII码是98),其实就是将’a’中的offset 6从0变成1,将offset 7从1变成0。
127.0.0.1:6379> get a"a"127.0.0.1:6379> setbit a 6 1(integer) 0127.0.0.1:6379> setbit a 7 0(integer) 1127.0.0.1:6379> get a"b"
getbit key offset
返回指定偏移量位的bit值,当key不存在时,返回0。
127.0.0.1:6379> getbit a 7(integer) 0127.0.0.1:6379> getbit a 6(integer) 1
bitcount key [start end]
用来统计字符串中被设置为1的比特数。默认检查整个字符串,当然也可以指定起始和结束位置。起始和结束位置可以是负数,例如-1表示最后一个字节,-2表示倒数第二字节,以此类推。
注意:
bitcount key 统计的bit位上出现1的个数, bitcount a 0 -1 就是整个字符串bit位上出现1的次数,
bitcount a 0 0 那么就应该是第一个字节中1的数量的,注意是字节,1个字节是8个bit位
setbit单位是bit,bitcount是以byte为间隔统计的
现在键a的值是’b‘,对应二进制是01100010,bit位上出现1的个数应该是3个
127.0.0.1:6379> bitcount a(integer) 3127.0.0.1:6379> bitcount a 1 2(integer) 0127.0.0.1:6379> bitcount a 0 1(integer) 3
bitop operation destkey key [key ...]
对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。
bitop 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数:
bitop and destkey key1 key2
:对一个或多个 key 求逻辑与,并将结果保存到 destkey
bitop or destkey key1 key2
:对一个或多个 key 求逻辑或,并将结果保存到 destkey
bitop xor destkey key1 key2
:对一个或多个 key 求逻辑异或,并将结果保存到 destkey
bitop not destkey key
:对给定 key 求逻辑非,并将结果保存到 destkey除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入,执行结果将始终保持到destkey里面。
与运算(and ):逻辑规则是两真才真,即遇0则0,如0111 0111
&&
1001 1001得0001 0001或运算(or ):逻辑规则是只有一个为真就为真,即遇1则1,如0111 0111
||
1001 1001得1111 1111异或运算(xor ):逻辑规则是两个不同就为真,如0111 0111
^
1001 1001得1110 1110非运算(not ):逻辑规则是反转操作数的含义,即取反,如
!
0111 0111 得1000 1000
bitpos key bit [start] [end]
该命令用于返回第一个被设置为0或1的位置。可以使用start和end参数指定查询范围,需要注意的是,这个范围指的是字节范围而不是位范围,也就是说start=0,end=2表示在前三个字节中查找。start和end都可以为负值,-1表示最后一位,-2表示倒数第二位,以此类推。
如果是空字符串,那么查找0和1都会返回-1。
现在键a的值是’b‘,对应二进制是01100010,如果查0应该返回0,查1应该返回1
127.0.0.1:6379> get a"b"127.0.0.1:6379> bitpos a 0(integer) 0127.0.0.1:6379> bitpos a 1(integer) 1
应用场景
需求:1千万的用户系统,统计用户一年内的登录天数,且时间周期随机
分析:一年按365天算,随机统计某个时间段内某个用户的登录天数,那就需要把每个用户365天的登录情况存起来,
如果使用mysql存那需要一个用户表,一个登录情况表,用户id关联,千万级的表对于占用的磁盘内存是很大的。
如果使用reids怎么做?只需要把用户名当作key,value使用365个bit位来代表365天,哪天登录了哪个bit就为1即可。这样算一个用户占365bit,8个bit位是1byte即一个用户占46byte,一千万用户占460,000,000byte约等449219kb约等438mb
实现,如zhangsan用户:
//zhangsan第一天登录了127.0.0.1:6379> setbit zhangsan 0 1(integer) 0//zhangsan第二天未登录127.0.0.1:6379> setbit zhangsan 1 0(integer) 0//zhangsan第三天未登录127.0.0.1:6379> setbit zhangsan 2 0(integer) 0//zhangsan第四天登录了127.0.0.1:6379> setbit zhangsan 3 1(integer) 0//zhangsan第五天登录了127.0.0.1:6379> setbit zhangsan 4 1(integer) 0//zhangsan第六天登录了127.0.0.1:6379> setbit zhangsan 5 1(integer) 0//zhangsan第七天登录了127.0.0.1:6379> setbit zhangsan 6 1(integer) 0//省略。。//第363天未登录127.0.0.1:6379> setbit zhangsan 362 0(integer) 0//第364天未登录127.0.0.1:6379> setbit zhangsan 363 0(integer) 0//第365天登录了127.0.0.1:6379> setbit zhangsan 364 1(integer) 0//查看字符长度46byte127.0.0.1:6379> strlen zhangsan(integer) 46//获取zhangsan第一周登录天总数,即五天127.0.0.1:6379> bitcount zhangsan 0 6(integer) 5//获取zhangsan最后三天登录情况,只登录1天127.0.0.1:6379> bitcount zhangsan -3 -1(integer) 1//全年登录共6天127.0.0.1:6379> bitcount zhangsan(integer) 6
需求:1千万用户的平台做活动,给用户送礼物,需要备货多少礼物。
分析:1千万用户,肯定不需要备1千万个礼物吧,平台用户分僵尸用户(注册完就不登录)和冷热用户(有时登录有事不登录)、忠诚用户(天天登录),那么如何对活跃用户统计?可以设定一个时间段,比如说 对1号~3号登录的用户数做统计,那么有可能某个用户1、2、3号都登录了,那就需要对这个用户去重,也就是这个用户3天都登录了,在这个时间段内也算作1个用户登录而不是3个。
redis实现:只需把日期作为key,把用户映射到某个bit位上,如张三用户对应0位,李四用户对应1位,王五对应2位。。。,该用户登录了,对应的bit位就是1。最后只需bitop or运算取值后再用bitcount 算出活跃用户总数即可。
//日张三登录了127.0.0.1:6379> setbit 0 1(integer) 0//日李四登录了127.0.0.1:6379> setbit 1 1(integer) 0//日王五登录了127.0.0.1:6379> setbit 2 1(integer) 0//日张三登录了127.0.0.1:6379> setbit 0 1(integer) 0//日李四登录了127.0.0.1:6379> setbit 1 1(integer) 0//取或运算存入count的值中127.0.0.1:6379> bitop or count (integer) 1//算出活跃用户总数,这三天共有三个用户登录了127.0.0.1:6379> bitcount count(integer) 3