Redis 的基础命令集合

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis 的基础命令集合

1、Hset  

hset(key, field, value)

将哈希表 hash 中域 field 的值设置为 value。

如果给定的哈希表并不存在, 那么一个新的哈希表将被创建并执行 HSET 操作。

如果field已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。

 HSET 命令在哈希表中新创建 field 域并成功为它设置值时, 命令返回 1 如果域 field 已经存在于哈希表, 并且 HSET 命令成功使用新值覆盖了它的旧值, 那么命令返回 0 

2、Hget    

hget(key, field):返回名称为key的hash中field对应的value

hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value

HGET 命令在默认情况下返回给定域的值。

如果给定域不存在于哈希表中, 又或者给定的哈希表并不存在, 那么命令返回 nil 


看了这个shell提示再结合概念理解起来就清楚很多了。

1、hset一条数据,并看懂其存储的数据结构。20190307182215465.png

2、这时候我们修改这个field中的value2019030718225154.png

这里的key就相当于tablename,如果域已经在hash表中,hset时会将旧值改为新值。

对于实际业务来说:

如果新增ope_id,定时器会定时刷新到redis的key = basicOpe中,final List<MOpeD> basicOpeList = dao2.find(MOpeD.class, "FROM MOpeD where validFlg = 'Y'");

basicOpeList.forEach(ope -> {

pipelined.hset("basicOpe", String.valueOf(ope.getOpeKey()), JacksonUtil.toJSONStr(ope));

//可以看出key是basicOpe,field是ope_key,value是ope_id

basicOpeData.put(String.valueOf(ope.getOpeKey()),JacksonUtil.toJSONStr(ope));

});

我新增一笔被刷新到redis中

如下图:20190307182343102.png可以看到下面就是一长串字符串就是 value。

实际业务是这样的,如果我在表中update了我新增的那笔valid_flg这个栏位。

等下一次定时器run完后,我再次查看这个key的这个field,竟然还存在。郁闷的我再次翻看 hset的定义:

如果field已经存在于哈希表中, 那么它的旧值将被新值value覆盖。

也就是说,我update的是value中的一个字段,fileld并未改变。所以old value不会被new value覆盖的。(7/31)


通过上面的例子的实践确实是如此,通过翻看代码,在业务层获取basicOpe的时候并不是hget而是hgetALL。

再看下图:20190307182427280.pnghgetAll得到了两行数据,从这个也可以看出hget 和hgetall的区别到底在哪里?

hgetall返回的是所有的域和值,本例来说,

“1) “00666”” - >key

“2)  “00625””-> value

在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。

最后再review代码时发现,hset bisicOpe的代码:

final List<MOpeD> basicOpeList = dao2.find(MOpeD.class, "FROM MOpeD where validFlg = 'Y'");

basicOpeList.forEach(ope -> {

pipelined.hset("basicOpe", String.valueOf(ope.getOpeKey()), JacksonUtil.toJSONStr(ope));

//可以看出key是basicOpe,field是ope_key,value是ope_id

basicOpeData.put(String.valueOf(ope.getOpeKey()), JacksonUtil.toJSONStr(ope));

});

从上面的代码可以看出,每次往basicOpe写值时的sql是塞valid_flg = 'Y'的。当在界面上删除这个ope时,db中将valid_flg赋值为N。这样basicOpe再也获取不在这条数据了,所以也不会有 “如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。”

为了解决这个问题,应该在实际的业务代码中加入,增量删除valid_flg = 'N’的数据:具体做法很简单,只需要找到valid_flg = ‘N’的field,然后hdel即可,如下:

 public void loadOpeBasicData(Jedis jedis){
        try {
            //3.Ope
            final List<MOpeD> basicOpeList = dao2.find(MOpeD.class, "FROM ***");
            List<MOpeD> basicOpeListToFlush = basicOpeList.stream().filter(mMopeD -> mMopeD.getValidFlg().equals("Y")).collect(Collectors.toList());// to flush
            List<MOpeD> basicOpeListToDel = basicOpeList.stream().filter(mMopeD -> mMopeD.getValidFlg().equals("N")).collect(Collectors.toList()); //to delete
            basicOpeListToFlush.forEach(ope -> {
                jedis.hset("basicOpe", String.valueOf(ope.getOpeKey()), JacksonUtil.toJSONStr(ope));
            });
            basicOpeListToDel.forEach(ope ->{
                jedis.hdel("basicOpe",String.valueOf(ope.getOpeKey()));//删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略.
            });
        } catch (Exception e) {
            logger.error(LoggerUtil.stackTraceToString(e));
            e.printStackTrace();
        }
    }

此外到前辈的这片博文:记Redis那坑人的HGETALL_SAP剑客的博客-CSDN博客目前我们的项目中仍有hgetAll的语法,因为实际业务之需求。

目前Coids QPS,时而也有OPS飙升的情况,不过目前redis的内存还够用,至于后续,随着业务的其他需要增多redis的使用,我想hgetall也是需要改善的。

-----------------update 2019年7月31日09:22:03----------------------------------

在实际业务中,遇到baiscMachinespec 这个key中有脏数据导致alarm发不出。后来查看了原因:

用户在界面维护了一笔数据,比如新增了machineName = ASSM0399 aliaslinename = ‘SIBW03’。用户某天删除了machineName = ASSM0399的那一笔数据,然后新增了machineName = ASSM0398 aliaslinename = ‘SIBW03’的一笔,对于machinename维护角度来说这没有问题,可是对RTM业务来说这样维护是会产生一对多的问题。baiscMachinespec的 field 是machinename。value 是 “"{\"aliaslinename\":\"OLBX0648\",\"department\":\"\xe5\xae\x9e\xe8\xa3\x85\xe7\xa7\x91\",\"machinename\":\"AOPS0609\"}"”

形如这种的value.

如何选取合适的filed 是需要考虑的

------------------update 2019年7月19日13:40:21------------------------------

有序集合

是set的一个升级版本,在set的基础上增加了一个顺序属性,这一属性在添加修改元素时可以指定,每次指定后zset会自动安装指定值重新调整顺序。可以理解为一张表,一列存value,一列存顺序。操作中的key理解为zset的名字。

Zset的最大元素数是2^32-1。

对于已经有序的zset,仍然可以使用SORT命令,通过指定ASC|DESC参数对其进行排序。

通过客户端help查看其用法

127.0.0.1:6380> help @sorted_set
  ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
  summary: Add one or more members to a sorted set, or update its score if it already exists
  since: 1.2.0
...............

zadd

ZADD key score member [[score member] [score member] ...]

127.0.0.1:6380> zadd testKey 1 var1
(integer) 1
127.0.0.1:6380> zadd testKey 2 var2
(integer) 1
127.0.0.1:6380> zadd testKey 3 var3
(integer) 1
127.0.0.1:6380> zrange testKey 0 -1 WITHSCORES
1) "var1"
2) "1"
3) "var2"
4) "2"
5) "var3"
6) "3"
add 同一个score,会写入新的kv
127.0.0.1:6380> zadd testKey 3 var3_1
(integer) 1
127.0.0.1:6380> zrange testKey 0 -1 withscores
1) "var1"
2) "1"
3) "var2"
4) "2"
5) "var3"
6) "3"
7) "var3_1"
8) "3"
add旧的value到新的socre中?
var3已经是有序集的成员,那么更新这个 var3 的score 值,并通过重新插入,来保证该 var3在正确的位置上。
如下例子所示
127.0.0.1:6380> zadd testKey 4 var3
(integer) 0
127.0.0.1:6380> zrange testKey 0 -1 withscores
1) "var1"
2) "1"
3) "var2"
4) "2"
5) "var3_1"
6) "3"
7) "var3"
8) "4"

--update 2022年8月26日14:37:18

zadd 的选项 XX NX CH INCR

XX: Only update elements that already exist. Don't add new elements. 只更新

NX: Only add new elements. Don't update already existing elements. 添加新元素不更新

CH: Modify the return value from the number of new elements added, to the total number of elements changed (CH is an abbreviation of changed). Changed elements are new elements added and elements already existing for which the score was updated. So elements specified in the command line having the same score as they had in the past are not counted. Note: normally the return value of ZADD only counts the number of new elements added.     update score和新增时zadd都有返回值。如果程序需要用到更新是否成功,这个返回值很有用。

INCR: When this option is specified ZADD acts like ZINCRBY. Only one score-element pair can be specified in this mode.  增加score

Starting with Redis version 3.0.2: Added the XX, NX, CH and INCR options.

Starting with Redis version 6.2.0: Added the GT and LT options.

127.0.0.1:19000> ZADD myzset  9999 "uno"
(integer) 0
127.0.0.1:19000> zrangebyscore myzset -inf +inf
1) "one"
2) "two"
3) "three"
4) "uno"
127.0.0.1:19000> zrangebyscore myzset -inf +inf withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "uno"
8) "9999"
10.50.10.236:19000> ZADD myzset NX 909090909 "uno"
(integer) 0
10.50.10.236:19000> zrangebyscore myzset -inf +inf withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "uno"
8) "9999"

45d8adde62454941b460cd033f10327e.png

有序集合可以干什么呢?

排行榜、有序时间以及评论+分页(评论是元素,score是分值,分页时给出score,按分页只需给传不同的score,动态分页也可以实现,在翻页时有新评论也不会有影响 ) 都可以采用这种集合来处理。


这个有序是如何实现的呢?

1、查看类型

127.0.0.1:6380> type testKey 
zset

2、查看底层数据结构

127.0.0.1:6380> OBJECT encoding  testKey 
"skiplist"

skiplist的底层原理是什么呢?

跳表(SkipList)数据结构介绍

当value的字节超过64字节时会存成skiplist,否则会直接存为ziplist。

127.0.0.1:6380> zadd k1 3.5 apple 7.2 orange 1.6 banana
(integer) 3
127.0.0.1:6380> OBJECT encoding k1
"ziplist"

----------------------update 2019年12月6日10:30:51----------------------------------------

zscan

Redis Zscan 命令用于迭代有序集合中的元素(包括元素成员和元素分值)

zscan history:A1300 0  match '*:*:*:*:*:**M' count 10000

2019120613181891.png

zrange(key,0,-1)

127.0.0.1:19000> zrange LINE_URL:/INDEX/201912/23/C2590INRP02.TXT 0 -1

1) "1577032690000 20191223003801 \\C1695A1CPK1\\C19CL\\C19CL01A\\C19CL01ACJ\\FORMAT\\C2590C19CL01ACJ.TXT#003810 1"

2) "1577033573000 20191223005243 \\C1695A1CPK1\\C19CJ\\C19CJ00A\\C19CJ00AAX\\FORMAT\\C2590C19CJ00AAX.TXT#005253 2"

3) "1577033621000 20191223005332 \\C1695A1CPK1\\C19CF\\C19CF04N\\C19CF04NAJ\\FORMAT\\C2590C19CF04NAJ.TXT#005342 3"

4) "1577033697000 20191223005452 \\C1695A1CPK1\\C19CK\\C19CK02M\\C19CK02MBP\\FORMAT\\C2590C19CK02MBP.TXT#005457 5"

5) "1577049900000 20191223052333 \\C1695A1CPK1\\C19CK\\C19CK03Q\\C19CK03QAQ\\FORMAT\\C2590C19CK03QAQ-1.TXT#052500 24"

6) "1577049981000 20191223052612 \\C1695A1CPK1\\C19BE\\C19BE061\\C19BE061BA\\FORMAT\\C2590C19BE061BA.TXT#052621 30"

7) "1577051094000 20191223054446 \\C1695A1CPK1\\C19CL\\C19CL01A\\C19CL01ACJ\\FORMAT\\C2590C19CL01ACJ-1.TXT#054454 104"

8) "1577051568000 20191223055239 \\C1695A1CPK1\\C19CK\\C19CK00N\\C19CK00NBL\\FORMAT\\C2590C19CK00NBL-1.TXT#055248 126"

9) "1577051639000 20191223055350 \\C1695A1CPK1\\C19CK\\C19CK02M\\C19CK02MBP\\FORMAT\\C2590C19CK02MBP-1.TXT#055359 128"

10) "1577051811000 20191223055642 \\C1695A1CPK1\\C19CG\\C19CG018\\C19CG018AP\\FORMAT\\C2590C19CG018AP-1.TXT#055651 132"

11) "1577051933000 20191223055844 \\C1695A1CPK1\\C19CF\\C19CF04N\\C19CF04NAJ\\FORMAT\\C2590C19CF04NAJ-1.TXT#055853 134"

zrangebyscore()

zrangebyscore(key, min, max):返回名称为key的zset中score >= min且score <= max的所有元素


Key:result:glass_id  

Value:actualEqptId,actualSubEqptId,defectCnt,glassId,ifPreProcess,OOC,OOS,panelCnt,preOpeId,processEndTime,ruleSeqId

Score:rule_id

查询命令:zrangebyscore result:A19C905MAL 269733 269733

Key:history:站点  

Value:主机台:子机台:recipe:prod:lot:glass:当前时间:F

Score:该片glass的ProcEndTime时间

查询命令:zrangebyscore history:A2353 1576544400 1576548000

显示整个有序集
ZRANGEBYSCORE history:ope -inf +inf
[root@P1QMSPL2RTM01 log]# redis-cli -p 6379 zrangebyscore history:C7777 -inf +inf
 1) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B031N00:C188900TBA:M"
 2) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B031N00:C188W02NBD:M"
 3) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C188S01TBT:M"
 4) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C188U021BV:M"
 5) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C1891023BH:M"
 6) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C189200SBN:M"
 7) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C189200SBS:M"
 8) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C1893008BN:M"
 9) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B055N00:C189300HAQ:M"
10) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B05PN00:C188W02SBT:M"
显示整个有序集及成员的 score 值
-inf 负无穷
+inf  正无穷
ZRANGEBYSCORE history:ope -inf +inf WITHSCORES    
[root@P1QMSPL2RTM01 log]# redis-cli -p 6379 zrangebyscore history:C7777 -inf +inf withscores
 1) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B031N00:C188900TBA:M"
 2) "1536626081"
 3) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B031N00:C188W02NBD:M"
 4) "1536626081"
 5) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C188S01TBT:M"
 6) "1536633079"
 7) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C188U021BV:M"
 8) "1536633079"
 9) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C1891023BH:M"
10) "1536633079"
11) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C189200SBN:M"
12) "1536633079"
13) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C189200SBS:M"
14) "1536633079"
15) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B03XN00:C1893008BN:M"
16) "1536633079"
17) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B055N00:C189300HAQ:M"
18) "1536644040"
19) "CHAN0300:CHAN0300:null:C1495A1ANK1:C189B05PN00:C188W02SBT:M"
20) "1536648516"

zrem

zrem(key, member) :删除名称为key的zset中的元素member

zremrangebyscore(key,score1,score2)

例如删除history:ope 17S - 18E的所有数据

zremrangebyscore history:A2355 1483200000 1546271999

zcard

zcard(key):返回名称为key的zset该key的value数量

127.0.0.1:6380> zcard testKey
(integer) 4

pipeLine

Redis之Pipeline使用注意事项_盒马coding的博客-CSDN博客

Redis中Pipeline的使用 - 段江涛IT - 博客园

pipeline 的默认的同步的个数为53个,也就是说arges中累加到53条数据时会把数据提交

---------------------------update 2019年8月10日10:30:18---------------

对List操作的命令

类似于key 从链表的两端取出数据。

20200507214359914.png

lrange

lrange(key, start, end):返回名称为key的list中start至end之间的元素(下标从0开始)

lrange key 0 -1 表示返回的时该key的所有数据,0代表起始 ,-1代表最后元素。(正负双向索引

Key:opehis:glassId

Value:站点:主机台:子机台:prod:ProcEndTime:当前时间:F

查询命令:lrange opehis:A19C905MAL 0 -1

rpush

rpush(key, value):在名称为key的list尾添加一个值为value的元素( r 代表右)

String opeValue = String.format("%s:%s:%s:%s:%s:%s:%s",opeId, eqptId, eqptId,prodId, epochSecond, evtTime, "F");
String opeKey = String.format("opehis:%s", glassId);
jedis.rpush(opeKey,opeValue);

rpop

rpop(key):返回并删除名称为key的list中的尾元素

lpush

lpush(key, value):在名称为key的list头添加一个值为value的 元素( l代表左)

Note: 允许重复元素,例如opehis:glass 此key

lpop

lpop(key):返回并删除名称为key的list中的首元素

ltrim

应用: "查看全文 "时候只show 一部分数据,当点击查看全文的时候再去DB获取。(这种设计非常合理,因为用户愿意点击查看全文就意味着用户愿意花费时间去等待获取需要的内容)

使用场景

1.String类型的应用场景

  String是最常用的一种数据类型,普通的key/value存储.

2.list类型的应用场景

  比较适用于列表式存储且顺序相对比较固定,例如:

省份、城市列表

品牌、厂商、车系、车型等列表

拆车坊专题列表...

3.set类型的应用场景

  Set对外提供的功能与list类似,当需要存储一个列表数据,又不希望出现重复数据时,可选用set

4.zset(sorted set)类型的应用场景

zset的使用场景与set类似,区别是set不是自动有序的,而zset可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序.当你需要一个有序的并且不重复的集合列表,那么可以选择zset数据结构。例如:

根据PV排序的热门车系车型列表

根据时间排序的新闻列表


 redis中各种数据类型对应的jedis操作命令_jack-zhu的博客-CSDN博客

20191221154032316.png

什么是二进制安全的?

C语言中的字符串是根据特殊字符“\0”来判断该字符串是否结束,对于字符串str="0123456789\0123456789”来说,在C语言里面str的长度就是10(strlen(str)=10),所以strlen()函数不是二进制安全的。而在Redis中,strlen str的结果是21,是二进制安全的(Redis底层所使用的字符串表示是Sds),它只关心二进制化的字符串,不关心字符串的具体格式,里面有啥字符,只会严格的按照二进制的数据存取,不会以某种特殊格式解析字符串。


20200507211242178.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
17天前
|
NoSQL Redis 数据库
Redis的全局命令及相关误区
Redis的全局命令及相关误区
22 0
|
25天前
|
NoSQL Redis 数据库
Redis中的常用命令有哪些?
Redis常用命令包括:PING测试连接,ECHO回显,SELECT切换数据库,QUIT关闭连接;KEYS查找key,EXISTS检查存在,DEL删除key,EXPIRE设置过期时间,TTL查看剩余生存时间,TYPE检测数据类型;STRING操作如SET/GET/MSET/MGET,INCR/DECR增减计数;HASH命令如HSET/HGET/HMSET/HMGET/HGETALL管理字段;LIST操作如LPUSH/RPUSH/LPOP/RPOP/LRANGE;
10 0
|
1月前
|
NoSQL Redis
Redis集群(六):集群常用命令及说明
Redis集群(六):集群常用命令及说明
194 0
|
1月前
|
缓存 NoSQL Java
【Redis】5、Redis 的分布式锁、Lua 脚本保证 Redis 命令的原子性
【Redis】5、Redis 的分布式锁、Lua 脚本保证 Redis 命令的原子性
63 0
|
2天前
|
存储 缓存 NoSQL
Redis入门到通关之Hash命令
Redis入门到通关之Hash命令
|
2天前
|
存储 缓存 NoSQL
Redis入门到通关之String命令
Redis入门到通关之String命令
|
8天前
|
存储 NoSQL Java
Redis 命令
Redis 命令
145 0
|
19天前
|
NoSQL Redis 数据库
通过migrate命令实现两个redis实例之间的数据迁移
通过migrate命令实现两个redis实例之间的数据迁移
|
1月前
|
NoSQL Redis 索引
[Redis]——Redis命令手册set、list、sortedset
[Redis]——Redis命令手册set、list、sortedset
|
2月前
|
存储 消息中间件 NoSQL
Redis相关命令详解及其原理
Redis相关命令详解及其原理
60 0

热门文章

最新文章