Redis菜鸟小结(二)

基本的Redis key的操作都已经熟悉了之后,便可以开始针对Redis提供的各种可操作的数据结构进行学习和了解。本文依旧是学习Redis的各种命令。

待补充--下述命令的讲解及理解;Jedis对应操作;Redis的事务等


首先先学习下Redis String下最常用的Set命令:

String的基本逻辑结构为key->value

SET

SET ${key} ${value}          [${exipire seconds}EX|${expire milliseconds}PX]         [NX|XX]

将一个key设置一个值,如果对应的key已经存在,则覆盖该key的值;注:操作前一定要check你要操作的key具体类型,或者明确具体类型,若你期望操作的key对应的结构为非String数据结构,则会直接覆盖成你新的数据结构。因此在key的定义上也要规避这种重复命名的情况

    时间复杂度O(1),当操作成功时会返回ok(为什么会有失败呢?因为有下面的几个可选参数)

    因为我们在Client未开始事务以及脚本操作的情况下,命令个是逐条到达Redis Server的,在两条命令中间可能会有其他插入的命令,来造成数据不安全,不一致的现象,因此,我们不建议设置key值,并设置过期时间通过如下方式:

    redis.set(key,value)    

    redis.expire(key,seconds)

这里存在两个问题,1、非原子性操作;2、两次通信交互,可能存在链接等待时间

因此,聪明的Redis设计者提供了如下几个可选参数:

EX (设置秒过期)设置一个值的时候,同时设置这个key的过期时间,单位是秒,与PX不同时出现

PX (设置毫秒过期)设置一个值的时候,同事设定这个key的过期时间,单位是毫秒,与EX不同时出现

EX/PX在命令中的位置为value后,如:SET mykey "myvalue" 1000 EX

NX (key不存在时设置)设置一个值之前,先检查对应的key是否存在,若key不存在则设置,若key存在时则不设置返回设置失败,与XX不同时出现

XX (key存在时设置)设置一个值之前,先检查对应的key是否存在,若key存在则覆盖设置,若key不存在则不设置返回设置失败,与NX不同事出现

NX/XX在命令中的位置为最后位置,如:SET mykey "myvalue" 1000 EX NX

NX一般可利用Redis的单线程原子性原理,来实现分布式锁,设置成功则持有锁,设置失败则未持有锁,为了避免锁的无限期存在,需要结合EX同时使用

XX可以用于分布式强制覆盖,在部分场景,我们只对存在的数据进行二次处理,但是不做数据初始化,对于这种场景,我们适用于XX来做覆盖。

SETNX

SETNX ${key} ${value} 对不存在的key设置一个value,若key已存在则设置失败,时间复杂度为O(1)

同理 SET ${key} ${value} NX

推荐使用SET命令代替,SET命令可以同步设置PX/EX避免永久锁的出现

SETEX

SETEX ${key} ${seconds} ${value} 设置key一个value,同步设置其过期时间,时间复杂度O(1)

同理 SET${key} ${value} ${seconds} EX

推荐使用SET命令代替

PSETEX

SETEX的毫秒版本,PSETEX ${key} ${milliseconds} ${value} 

推荐使用SET命令代替

MSET

MSET ${key1} ${value1} [${key2} ${value2} ...${keyn}${valuen}] 批量进行多key的同时赋值,时间复杂度为O(N),N为操作的key数

这个命令可以理解为多次操作SET,即 MSET key1 "value1" key2 "value2",可以转换为:

SET key1 "value1"

SET key2 "value2"

但是,不推荐这样使用。

MSET自身是原子性,批量设置非常合适,可以避免网络异常问题等,适用需要全部成功或全部失败的情况。

且这里的通讯交互仅一次,可有效避免重复的获取通讯链接的等待时间

批量操作key一般推荐是20个左右一次操作,避免对server进行阻塞,降低redisserver的性能,引起其他需要快速返回的请求

MSETNX

MSETNX ${key1} ${value1} [${key2} ${value2} ...${keyn}${valuen}]   批量进行多key的同时赋值,仅所有key均不存在时可操作成功,若有key存在则操作失败,且全部失败,具有原子性。时间复杂度为O(N),N为操作的key数

MSETNX 适用于 多资源条件锁,当你在执行某个操作的时候,你需要多个条件资源,如:

你准备写一个数据合并消费程序,其中由多个程序为你生产数据,他们使用不同的通道,为了保证通道数据传输准确,你期望在获取数据的时候不能生产,生产数据的时候不能读取,且你期望各生产者能够最大力度的生产消息,自己可以接受消费后置,则可以推荐使用这个MSETNX命令,可以做到多个资源的同时上锁,如果某一个key无法上锁,也不会修改其他可操作的数据值,即这是一个等待代价很高的锁。

但。正如我上面所说的,我们期望每个所都带有一定的过期时间,使用这个命令,无法保证每个锁都是带有过期时间的。

批量操作key一般推荐是20个左右一次操作,避免对server进行阻塞,降低redisserver的性能,引起其他需要快速返回的请求

SETBIT

SETBIT ${key} ${offset} ${value} 在指定偏移量上设置其二进制数,形成一个bitmap;时间复杂度为O(1), offset的取值在0~2^32-1(512MB之内)

注意的操作offset相当于是高位开始计数,默认按字节分割(即八位),想要观察自己设置的结果,可以用setbit 操作完成后使用get获取一下

如:setbit mybit 0 1  生成的结果为: 1000 0000   

setbit mybit 8 1 生成的结果为: 0000 0000   1000 0000

因为SETBIT的操作形式,如果OFFSET设置过大,会在首次操作时,让Redis生成这个bitmap较久,第二次则不会重新分配空间,因此想要使用请注意offset的大小

该命令可以结合BITCOUNT,BITOP,GETBIT等用于行为操作统计或分析:

如:统计当日用户浏览某页面UV,key为当日生成key,offset为uid等。

学好二进制这些东西就能很容易的理解,和找到巧妙的使用场景啦~

SETRANGE

SETRANGE ${key} ${offset} ${value} 在指定offset偏移量上进行value的字符串覆写,对于无字符串覆盖部分,Redis使用\x00占位填充

SETBIT是针对偏移量上的二进制进行覆写来理解的话,SETRANGE就是在指定偏移量上进行字符串的覆写,同SETBIT,可写入的内存限制在了512MB,即OFFSET限定在了0~2^29-1(字符默认占用1个字节,即2^3(8bit))

时间复杂度上为O(M)M为字符串长度(据说在小字符串情况下平摊复杂度是O(1))待读源码

返回值是修改后的字符串长度

GETSET

GETSET ${key} ${value}  覆写一个key的value,并返回旧值,若key不是字符型,则抛错,时间复杂度O(1)

返回值为旧值,当key不存在时返回nil

这个命令是原子性获取原值的命令,可以用于很多,我们做替换型操作的命令,如抢夺,接力等。

也可用于计数归零操作,方便记录归零前数据。


接下来是与SET对应的GET命令:

GET

GET ${key} 获取key对应的value,若key对应的value结构非String类型会返回一个错误,时间复杂度为O(1)

返回值为:key对应的String值,若不存在则为nil,若结构不是String则返回一个错误

MGET

MGET ${key1} [${key2}...${keyn}] 同时获取多个key对应的value,返回一个列表,时间复杂度为O(N) N为key的数量

注意:这个命令不会报错,哪怕你的key对应的结构不是string,也不会报错,只会在对应的位置返回nil

因为返回值为一个列表,因此在获取结构时,务必注意保存结构的顺序,根据顺序匹配结果

另外,多key获取数据时,不推荐使用 get key1  get key2 ...多部操作,而是推荐mget操作,减少命令操作对链接获取的等待时间

批量操作key一般推荐是20个左右一次操作,避免对server进行阻塞,降低redisserver的性能,引起其他需要快速返回的请求

GETBIT

GETBIT ${key} ${offset} 主要针对 SETBIT的存储结果进行查询,获取偏移量在offset位置的二进制数据,时间复杂度O(1),返回值 0或1,若类型非String,则返回一个错误

当利用SETBIT生成一个BITMAP的时候,GETBIT是很好的获取对应位数据的命令

GETRANGE

GETRANGE ${key} ${start}${end} 获取key对应字符串的start 偏移量到end偏移量之间的字符串,时间复杂度O(N),N为待返回的字符串长度

start 为开始字符,从左开始计数为0,当为负数时,表示从右开始计数的第n个,如-1,表示右侧第一个字符

end同理,为结束字符

举例说明:

字符串:set myrange  "0123456789abcdef"

getrange myrange 0 10 ------>"0123456789a"

getrange myrange 10 15 ------>"abcdef"

getrange myrange 12 20 ------>"cdef"

getrange myrange 0 -1 ------>"0123456789abcdef"

getrange myrange 0 -2 ------>"0123456789abcde"

getrange myrange -1 -2 ------>""


接下来是一些用于叠加器:

INCRBY

  INCRBY ${key} ${increment}  将key对应的数值按increment的幅度增加,increment必须是一个整数(可以为负数,负数则较为类似一个decr),如果key不存在则先初始化为0,然后执行incrby操作,即,若key: myincr不存在,执行 INCRBY myincr 10 的执行结果为10,时间复杂度是O(1),返回值就是执行incrby之后的key对应的结果,当key对应的结构不是String,且不是integer类型的数据时,会提示一个错误(即负数也是可以的)。注:该命令的值限制在-2^63~2^63-1(即64bit内)

该命令主要用于计数,分布式任务执行同步,累计步幅,和expire结合使用可以做分时限流,再结合setrange甚至可以完成统计并记录到时间序列上

INCR

INCR ${key} 将key对应的数值按增幅为1的幅度增加,如果key不存在则先初始化为0,然后再执行incr操作,实际上等于incrby ${key} 1,时间复杂度是O(1),返回值就是执行incr之后的key对应的结果,当key对应的结构不是String,且不是integer类型的数据时,会提示一个错误(即负数也是可以的)。注:该命令的值限制在-2^63~2^63-1(即64bit内)

INCRBYFLOAT

  INCRBY ${key} ${increment} 将key对应的述职按increment的幅度增加,increment必须是一个可以转换为双精度浮点数的数值(可以为负数),如果key不存在则先初始化为0,然后执行incrbyfloat操作,时间复杂度是O(1),返回值就是执行incrbyfloat之后的key对应的结果,当key对应的结构不是String,且不是数值类型的数据时,会提示一个错误。注:命令的小数要注意小数点最多保留小数点后17位


递减器:

DECRBY

DECRBY ${key} ${increment}  将key对应的数值按increment的幅度减少,increment必须是一个整数(可以为负数,负数则较为类似一个incr),如果key不存在则先初始化为0,然后执行decrby操作,即,若key: mydecr不存在,执行 DECRBY mydecr 10 的执行结果为-10,时间复杂度是O(1),返回值就是执行decrby之后的key对应的结果,当key对应的结构不是String,且不是integer类型的数据时,会提示一个错误(即负数也是可以的)。注:该命令的值限制在-2^63~2^63-1(即64bit内)

可用做最大重试次数,或最大次数限定

DECR

DECR ${key} 将key对应的数值按增幅为1的幅度减少,如果key不存在则先初始化为0,然后再执行decr操作,实际上等于decrby ${key} 1,时间复杂度是O(1),返回值就是执行incr之后的key对应的结果,当key对应的结构不是String,且不是integer类型的数据时,会提示一个错误(即负数也是可以的)。注:该命令的值限制在-2^63~2^63-1(即64bit内)


字符长度:

STRLEN

STRLEN ${key} 返回key对应字符串的字符长度,时间复杂度是O(1),返回值为字符串的字符长度,就算是数值也是按字符串方式获取其长度,若key不存在,则返回0,若key不是字符串,则返回一个错。(Redis底层使用SDS结构,内置字符长度,因此时间复杂度为O(1))


字符拼接:

APPEND

APPEND ${key} ${value} 在key对应的字符串后面追加value字符串,并返回其追加后的字符串长度。时间复杂度平摊O(1)(原因待学习)。返回值:拼接后的字符串的长度。若key不存在则相当于set命令,若key对应的值非String类型,则返回一个错误。


位运算:

BITCOUNT

BITCOUNT ${key} [${start}] [${end}] 获取start到end之间位之和,时间复杂度O(N),N为待返回的字符串长度

start 为开始字符,从左开始计数为0,当为负数时,表示从右开始计数的第n个,如-1,表示右侧第一个字符

end同理,为结束字符

BITOP

BITOP ${OP} ${dest} ${key1} [${key2}...${keyn}] 将key1到keyn 这些key对应的位内容进行OP操作,并将操作结果保存至以dest为key的结果内,同时返回操作结果的长度,时间复杂度为O(N),对大型矩阵的操作要避免在master操作,避免阻塞

OP 包含: AND (并) OR(或)XOR(异或)NOT(非)

注:非情况,仅支持一个key


OK

OK


大家读完一遍之后,发现,哎呀,咋感觉这么乱呢。

其实是上面,只是按照命令操作类型进行了排序,如果还有一些困惑的同学,可以按照下述顺序再进行一次学习:

对于String下面的更多类型来分解:

数值类型:(注意除了incr,decr这类按照数值进行操作,有数值依赖的操作外,其他均将对数值当字符操作)

初始化、覆盖可以使用:SET;

批量初始化、覆盖可以使用:MSET;

获取可以使用:GET;

批量获取可以使用:MGET;

设置过期可以使用EXPIRE;

原子性简单SET & EXPIRE 可以使用SETEX,当然也可以使用 SET EX;

设置毫秒级过期可以使用PEXPIRE;

原子性简单SET & PEXPIRE 可以使用PSETEX,当然也可以使用 SET PX;

设置前检查值是否存在可以使用:EXISTS;

原子性简单EXISTS & SET 可以使用 SETNX, 淡然也可以使用 SET NX;

同时对多个key设置SETNX,可以使用MSETNX;

如果希望SETNX + SETEX 必须使用 SET EX NX;

增加整型数字可以使用:INCR、有步幅设置的可以使用:INCRBY;

增加浮点型数字可以使用:INCRBYFLOAT;

减少整型数字可以使用:DECR、有步幅设置的可以使用:DECRBY;

如果希望设置一个值前,先获取下之前的值,可以 使用GETSET;

位运算,bit类型:(注意bit类型的操作也可被其他操作覆盖修改,要注意避免冲突使用)

设置某个位上的值,可以使用SETBIT;

对应获取某个位上的值,可以使用GETBIT;

获取指定范围内,位值和,可以使用BITCOUNT;

如果希望进行常规的位运算,可以使用BITOP;

上述内容,除了强制要求数值类型的操作外;均可操作这类位运算的结果;

纯字符类型:

初始化、覆盖可以使用:SET;

批量初始化、覆盖可以使用:MSET;

获取可以使用:GET;

批量获取可以使用:MGET;

设置过期可以使用EXPIRE;

原子性简单SET & EXPIRE 可以使用SETEX,当然也可以使用 SET EX;

设置毫秒级过期可以使用PEXPIRE;

原子性简单SET & PEXPIRE 可以使用PSETEX,当然也可以使用 SET PX;

设置前检查值是否存在可以使用:EXISTS;

原子性简单EXISTS & SET 可以使用 SETNX, 淡然也可以使用 SET NX;

同时对多个key设置SETNX,可以使用MSETNX;

如果希望SETNX + SETEX 必须使用 SET EX NX;

如果希望设置一个值前,先获取下之前的值,可以 使用GETSET;

设置字符串内范围值,可以使用SETRANGE;

获取字符串内范围值,可以使用GETRANGE;

字符串拼接覆盖,可以使用APPEND;

高效获取字符长度,可以使用STRLEN;



如果只是常规操作字符串,那么就记好:

SET 默认不过期,后追EXPIRE操作非原子性,使用SET EX(PX)更省心

想用Redis做锁,用好SETNX,后追EXPIRE操作非原子性,使用SET EX(PX)NX更省心

获取数据用GET,不是必须提前用EXISTS

循环操作SET、GET浪费Client的网络和链接,可以用MSET、MGET减少链接次数(注意避免过大操作)

其他类型根据情况可以巧用~

掰掰~


RedisKey的命令

Redis数据结构

Redis数据结构的命令

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容