Hset
将哈希表 hash 中域 field 的值设置为 value。
如果给定的哈希表并不存在, 那么一个新的哈希表将被创建并执行 HSET 操作。
如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。
当 HSET 命令在哈希表中新创建 field 域并成功为它设置值时, 命令返回 1 ; 如果域 field 已经存在于哈希表, 并且 HSET 命令成功使用新值覆盖了它的旧值, 那么命令返回 0 。
Hget
返回哈希表中给定域的值
HGET 命令在默认情况下返回给定域的值。
如果给定域不存在于哈希表中, 又或者给定的哈希表并不存在, 那么命令返回 nil 。
----------------------------------------------------------------------------------------------------------------------
看了这个shell提示再结合概念理解起来就清楚很多了。
1、hset一条数据,并看懂其存储的数据结构。
2、这时候我们修改这个field中的value
这里的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中
如下图:
可以看到下面就是一长串字符串就是 value。
实际业务是这样的,如果我在表中update了我新增的那笔valid_flg这个栏位。
等下一次定时器run完后,我再次查看这个key的这个field,竟然还存在。郁闷的我再次翻看 hset的定义:
如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。
也就是说,我update的是value中的一个字段,fileld并未改变。所以old value不会被new value覆盖的。(7/31)
通过上面的例子的实践确实是如此,通过翻看代码,在业务层获取basicOpe的时候并不是hget而是hgetALL。
再看下图:
hgetAll得到了两行数据,从这个也可以看出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 basicOpeList = dao2.find(MOpeD.class, "FROM ***");
List basicOpeListToFlush = basicOpeList.stream().filter(mMopeD -> mMopeD.getValidFlg().equals("Y")).collect(Collectors.toList());// to flush
List 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();
}
}
此外到前辈的这片博文:https://blog.csdn.net/zhongguomao/article/details/52095883。目前我们的项目中仍有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.
-----------------------update 2019年7月19日13:40:21---------------------------------------
zrangebyscore()
pipeLine
https://blog.csdn.net/xfg0218/article/details/75353875
https://www.cnblogs.com/duanjt/p/10245620.html
pipeline 的默认的同步的个数为53个,也就是说arges中累加到53条数据时会把数据提交
-----------------------------------------------update 2019年8月10日10:30:18-----------------------------------
lrange
返回列表 key
中指定区间内的元素,区间以偏移量 start
和 stop
指定。
lrange key 0 -1 表示返回的时该key的所有数据,0代表起始 ,-1代表最后元素。