Redis 的基础命令集合

简介: 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

目录
相关文章
|
12月前
|
存储 缓存 监控
Redis设计与实现——Redis命令参考与高级特性
Redis 是一个高性能的键值存储系统,支持丰富的数据类型(字符串、列表、哈希、集合等)和多种高级功能。本文档涵盖 Redis 的核心命令分类,包括数据类型操作、事务与脚本、持久化、集群管理、系统监控等。特别介绍了事务的原子性特性、Lua 脚本的执行方式及优势、排序机制、发布订阅模型以及慢查询日志和监视器工具的使用方法。适用于开发者快速掌握 Redis 常用命令及其应用场景,优化系统性能与可靠性。
479 12
|
8月前
|
存储 缓存 NoSQL
Redis基础命令与数据结构概览
Redis是一个功能强大的键值存储系统,提供了丰富的数据结构以及相应的操作命令来满足现代应用程序对于高速读写和灵活数据处理的需求。通过掌握这些基础命令,开发者能够高效地对Redis进行操作,实现数据存储和管理的高性能方案。
248 12
|
8月前
|
存储 消息中间件 NoSQL
【Redis】常用数据结构之List篇:从常用命令到典型使用场景
本文将系统探讨 Redis List 的核心特性、完整命令体系、底层存储实现以及典型实践场景,为读者构建从理论到应用的完整认知框架,助力开发者在实际业务中高效运用这一数据结构解决问题。
|
10月前
|
NoSQL Redis
Lua脚本协助Redis分布式锁实现命令的原子性
利用Lua脚本确保Redis操作的原子性是分布式锁安全性的关键所在,可以大幅减少由于网络分区、客户端故障等导致的锁无法正确释放的情况,从而在分布式系统中保证数据操作的安全性和一致性。在将这些概念应用于生产环境前,建议深入理解Redis事务与Lua脚本的工作原理以及分布式锁的可能问题和解决方案。
347 8
|
9月前
|
存储 缓存 人工智能
Redis六大常见命令详解:从set/get到过期策略的全方位解析
本文将通过结构化学习路径,帮助读者实现从命令语法掌握到工程化实践落地的能力跃迁,系统性提升 Redis 技术栈的应用水平。
|
12月前
|
存储 缓存 NoSQL
Redis中的常用命令-get&set&keys&exists&expire&ttl&type的详细解析
总的来说,这些Redis命令提供了处理存储在内存中的键值对的便捷方式。通过理解和运用它们,你可以更有效地在Redis中操作数据,使其更好地服务于你的应用。
594 17
|
12月前
|
消息中间件 NoSQL Linux
Redis的基本介绍和安装方式(包括Linux和Windows版本),以及常用命令的演示
Redis(Remote Dictionary Server)是一个高性能的开源键值存储数据库。它支持字符串、列表、散列、集合等多种数据类型,具有持久化、发布/订阅等高级功能。由于其出色的性能和广泛的使用场景,Redis在应用程序中常作为高速缓存、消息队列等用途。
1052 16
|
JSON NoSQL Redis
在Rocky9系统上安装并使用redis-dump和redis-load命令的指南
以上步骤是在Rocky9上使用redis-dump和redis-load命令顺利出行的秘籍。如果在实行的过程中,发现了新的冒险和挑战,那么就像一个勇敢的航海家,本着探索未知的决心,解决问题并前进。
415 14
|
12月前
|
消息中间件 NoSQL Unix
Redis的基本特性以及其基础命令用法
这只是冰山一角,Redis的强大功能和简洁的操作方法值得我们深入了解和掌握,是复杂数据问题解决的有力工具。所以,来一场有趣的Redis冒险吧!
366 6
|
缓存 NoSQL Redis
Redis如何优化频繁命令往返造成的性能瓶颈?
频繁的命令往返是Redis性能优化中需要重点关注的问题。通过使用Pipeline、Lua脚本、事务、合并命令、连接池以及合理设置网络超时,可以有效减少网络往返次数,优化Redis的性能。这些优化措施不仅提升了Redis的处理能力,还能确保系统在高并发情况下的稳定性和可靠性。
344 14