• 【redis-02】redis的五种数据类型和对应的操作方法,补充RedisUtil模板


    【redis-02】redis的五种数据类型和对应的操作方法,补充RedisUtil模板

    (1)redis的五种数据类型

    1-String:字符串
    2-List:列表
    3-Hash:哈希字典
    4-Set:集合
    5-Sorted Set:有序集合

    (2)String:字符串常用命令

    (2-1)String基本信息

    存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
    存储数据的格式:一个存储空间保存一个数据
    存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用(但是仍是字符串)

    (2-2)String常用命令

    SET key value                   设置key=value
    GET key                         获得键key对应的值
    SETNX key value                 设置键的值,只有当该键不存在
    SETEX key seconds value         键到期时设置值
    MSET key value [key value...]   设置多个键和多个值
    MSETNX key value [key value...] 设置多个键多个值,只有在当没有按键的存在时
    PSETEX key milliseconds value   设置键的毫秒值和到期时间
    DEL key                         如果存在删除键
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (2-3)String业务场景一(String类型作为数值时的增减)

    业务场景描述

    大型企业级应用中,常见分表操作,使用多张表存储同类型数据,但是对应的主键id必须保证统一性,不能重复。
    Oracle数据库具有sequence设定,可以解决该问题,但是mysql数据库并没有类似的机制,如何解决?

    解决方案

    设置数值数据增加指定范围的值

    incr key 			//自增1
    incrby key increment  //增加指定数值
    incrbyfloat key increment  //增加一个浮点数
    
    • 1
    • 2
    • 3

    设置数值数据减少指定范围的值

    decr key 			//自减1
    decrby key increment //减少指定数值
    
    
    • 1
    • 2
    • 3

    String作为数值操作时的注意事项

    1. string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算
    2. redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响。
    3. 按数值进行操作的数据,如果原始数据不能转成数值,或超过了redis数值上线范围,将会报错。9223372036854775807 (java中long型数据最大值,Long.MAX_VALUE)

    (2-4)String业务场景二(数据时效性设置)

    场景描述

    1. 场景一:“某某综艺”,启动海选投票,只能通过微信投票,每个微信号每4个小时只能投1票。
    2. 场景二:电商商家开启热门商品推荐,热门商品不能一直处于热门期,每种商品热门期维持3天,3天后自动取消热门
    3. 场景三:新闻网站会出现热点新闻,热点新闻最大的特征是对时效性,如何自动控制热点新闻的时效性

    解决思路

    给用户设置一个唯一的id,并为其设置一个有效时长,当时间已经超过设定时间后将id删除。

    解决方案

    redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作:

    setex key seconds value //增加、修改键值对并为其设定生命周期
    psetex key milliseconds value //功能与上面一直,秒的单位不同
    
    • 1
    • 2

    例如:setex name 10 time,超过10s以后再get name就发现没有这个值了

    String类型设置生命周期时的注意事项

    (2-5)String业务场景三(高热度数据访问加速)

    场景描述

    主页高频访问信息显示控制,例如微博大V主页显示粉丝数与微博数量,这些数据就是热度数据,不断发生变化,这些数据如何放入redis?

    解决方案

    (1)实现方式一:在redis中为大V用户设定用户信息,以用户主键和属性值为key,后台设定时间定时刷新即可
    (2)在redis中以json格式存储大V用户,定时刷新

    set user: id :5765898790 {id:5765898790,focuss:3050,fans:117492300,blogs:117744}
    
    • 1

    (3)List:列表

    (3-1)List基本信息

    数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
    需要的存储数据:一个存储空间保存多个数据,且通过数据可以体现进入顺序
    list类型:保存多个数据,底层使用双向链表存储结构实现

    (3-2)List常用命令

    LPUSH key value1 [value2]  在前面加上一个或多个值的列表
    LLEN key 							   获取列表的长度
    RPUSH key value1 [value2]  添加一个或多个值到列表
    LRANGE key start stop 	   从一个列表获取各种元素
    RPOP key                   取出并获取列表中的最后一个元素
    LPOP key                   获取并取出列表中的第一个元素
    lindex key index           查询第i个元素
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (3-3)List类型数组扩展操作

    blpop key1 [key2] timeout
    brpop key1 [key2] timeout
    
    • 1
    • 2

    阻塞式获取,在规定时间内获取这个值,规定时间内如果还没有的时候可以等,直到有值就可以获取到获取超时获取为空。
    开两个客户端,一个设置15s内获取list1中的值,此时list1位空一直等待(阻塞),在15秒内另一个客户端存入到list1中数据,此时就被获取到。

    (3-4)List类型数据业务场景一(点赞消息列表)

    场景描述

    微信朋友圈点赞,要求按照点赞顺序显示点赞好友信息。
    如果取消点赞,移除对应好友信息。

    解决方案

    移除指定数据

    lrem key count value //count为移除的数量,value为移除哪个值
    
    • 1

    点赞的时候,使用rpush往list尾部按顺序加入数据
    移除好友的时候,使用lrem daqiao 2 zhangfei 来从list中移除

    List类型数据操作注意事项

    (1)list 中保存的数据都是string类型的,数据总容量式是有限的,最多232-1个元素(4294967295)
    (2)list具有索引的概念,但是操作数据时候通常以队列的形式进行入队出队操作,或以栈的形式进入栈出栈的操作
    (3)获取全部数据操作结束索引设置为-1
    (4)list 可以对数据进行分页操作,通过第一页的信息来自list,第2页及更多的信息通过数据库的形式加载

    (3-5)List类型数据业务场景二(最新消息的展示)

    场景描述

    (1)twitter、新浪微博、腾讯微博中个人用于的关注列表需要按照用户的关注顺序进行展示,粉丝列表需要将最近关注的粉丝列在前面
    (2)新闻、资讯类网站如何将最新的新闻或资讯按照发生的事件顺序展示
    (3)企业运营过程中,系统将产生出大量的运营数据,如何保障堕胎服务器操作日志的统一顺序输出?

    解决方案

    (1)依赖list的数据具有顺序的特征对信息进行管理
    (2)使用队列模型解决多路信息汇总合并的问题
    (3)使用栈模型解决最新消息的问题

    (4)Hash:字典

    (4-1)Hash基本信息

    String类型存储的困惑
    对象类数据的存储如果具有较为频繁的更新需求,操作会显得笨重,存容易,改麻烦。
    为了区别与Redis中的键值对的称呼,hash中的键成为field,而key特征Redis的键。
    在这里插入图片描述
    hash类型
    新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
    需要的内存结构:一个存储空间保存多少个键值对数据
    hash类型:底层使用哈希表结构实现数据存储

    (4-2)Hash常用命令

    HSET key field value 设置对象指定字段的值
    HGET key field 获取对象中该field属性域的值
    HGETALL key 获取对象的所有属性域和值
    HKEYS key 获取对象的所有属性字段
    HVALS key 获取对象的所有属性值
    HLEN key 获取对象的所有属性字段的总数
    HSETNX key field value 只在对象不存在指定的字段时才设置字段的值
    hdel key field1 [field2]  删除数据
    hmset key field1 value1 field2 calue2	添加/修改多个数据
    hmget key field1 field2 …	获取多个数据
    hexists key field		获取哈希表中是否存在指定的字段
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (4-3)hash类型数据扩展操作

    获取哈希表中所有的字段名和字段值

    hkeys key //字段名
    hvals key //字段值
    
    • 1
    • 2

    设置指定字段的数值数据增加指定范围的值

    hincrby key field increment //指定数值增长指定的数
    hincrbyfloat key field increment
    
    • 1
    • 2

    案例:user1年龄增加2岁,曾增加0.5岁

    (4-4)hash类型数据操作的注意事项

    (1)hash类型下的value只能存储字符串,不允许存储其他类型数据,不存在嵌套现象。如果数据未获取到,对应的值为(nil)
    (2)每个hash可以存储232-1个键值对
    (3)hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计不是为了存储大量对象的,切记不可滥用,更不可以将hash作为对象列表使用
    (4)hgetall操作可以获取全部属性,如果内部fiekd过多,遍历整体数据效率就会很低,有可能成为数据访问瓶颈。

    (4-5)hash数据类型业务场景一(购物车)

    场景描述

    电商网站购物车的设计和实现
    在这里插入图片描述

    解决方案

    (1)思路

    (2)代码案例
    例如创建一个购物车:

    (3)优化思路
    当前仅仅是将数据存储到redis中,并没有起到加速的所用,因为我们仅仅查询到了用户的id和商品的id,显示的时候显示的用户名和商品的名称,商品信息还需要二次查询数据库。

    1-每条购物车中的商品记录保存成两条field
    2-field1 专用于保存购买数量
    命名格式:商品id:nums
    保存数据:数值
    3-field2 专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等等
    命名格式:商品id:info
    保存数据:json在这里插入图片描述

    但是出现很多用户都将同一个商品假如购物车,就会出现大量的重复信息,例如商品信息重复:
    在这里插入图片描述因此我们可以将商品的信息单独的保存成一个哈希。

    (4)创建数据,如果有则不再创建,如果没有则创建

    hsetnx key field value
    
    • 1

    (4-6)hash数据类型业务场景二(实现抢购、限购发放优惠券、激活码)

    业务描述

    双11活动日,销售手机充值卡的上级啊对移动、联通、典型的30元、50元、100元商品退出抢购活动,每种商品抢购上限1000张

    解决方案

    (1)以商家id作为key
    (2)将参与抢购的商品id作为field
    (3)将参与抢购的商品数量作为对应的value
    (4)抢购时使用降至的方式控制产品数量

    (5)Set:集合

    (5-1)基本信息

    (1)新的存储需求:存储大量的数据,在查询方面提供更高的效率
    (2)需要的存储结构:能够保存大量的数据,搞笑的内部存储机制,便于查询
    (3)set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值式不允许重复的。也就是只有键没有值的hash

    (5-2)Set常用命令

    SADD key member [member ...] 添加一个或者多个元素到集合(set)里
    SCARD key 获取集合里面的元素数量
    SMEMBERS key 获取集合里面的所有key
    SPOP key [count] 获取并删除一个集合里面的元素
    srem key member1 [member2]   删除数据
    sismember key member    判断集合中是否包含指定数据
    srandmember key [count]   随机获取集合中指定数量的数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (5-3)set类型数据业务场景一(随机操作数据)

    场景描述

    每位用户首次使用进入头条时候会设置3项爱好的内容,但是后期为了增加用户的活跃度,兴趣点,必须让用户对其他信息类别逐渐产生兴趣,增加客户留存度,如何实现?

    解决思路

    (1)系统分析出各个分类的最新或最热点信息条目并组织成set集合
    (2)随机挑选其中部分信息
    (3) 配合用户关注信息分类中的热点信息组织展示的全信息集合

    解决方案

    redis应用于随机推荐类信息检索,例如热点歌单推荐,热点新闻推荐,热点旅游线路,应用APP推荐,大V推荐等。

    (5-4)set类型数据业务场景二(共同好友)

    场景描述

    (1)新浪微博为了增加用户热度,提高用户留存性,需要微博用户在关注更多的人,以此获得更多的信息或热门话题,如何提高用户关注他人的总量?
    (2)qq新用户入网年龄越来越低,这些用户的朋友圈交际圈非常小,往往集中在一所学校甚至一个班级中,如何帮助用户快速积累好友用户带来更多的活跃度?
    (3)微信公众号是微信信息流通的渠道之一,增加用户关注的公众号成为提高用户活跃度的一种方式,如何帮助用户积累更多关注的公众号?
    (4)美团外卖为了提升成单量,必须帮助用户挖掘没事需求,如何推荐给用户最合适自己的美食?

    解决方案

    (1)求两个集合的交、并、差集

    sinter key1 [key2] //交集
    sunion key1 [key2] //并集
    sdiff key1 [key2] //差集(key1有但是key2没有的)
    
    • 1
    • 2
    • 3

    (2)求两个集合的交、并、差集并存储到指定集合中

    sinterstore destination key1 [key2]
    sunionstore destination key1 [key2]
    sdiffstore destination key1 [key2]
    
    • 1
    • 2
    • 3

    (3)将指定数据从原始集合移动到目标集合中

    smove source destination member
    
    • 1

    redis应用于同类信息的关联搜索,二度关联搜索,深度关联搜索

    (1)显示共同关注(一度)
    (2)显示共同好友(一度)
    (3)由用户A出发,获取到好友用户B的好友信息列表(一度)
    (4)由用户A出发,获取到好友用户B的购物清单列表(二度)
    (5)由用户A出发,获取到好友用户B的游戏充值列表(二度)

    Set类型数据操作的注意事项

    set类型不允许数据重复,如果添加的数据在set中已经存在,将只保留一份
    set虽然与hash的存储结构相同,但是无法启用hash中存储值的空间

    (5-5)set类型数据业务场景三(同类型不重复数据的合并操作)

    场景描述

    集团公司共具有12000名员工,内部oa系统中具有700多个角色,3000多个业务操作,23000多种数据,每位员工具有一个或多个角色,如何快速进行业务操作的权限校验

    解决方案

    依赖set集合数据不重复的特征,依赖set集合hash存储结构特征完成数据过滤与快速查询
    (1)根据用户id获取用户所有角色
    (2)根据用户所有角色获取用户所有操作权限放入set集合
    (3)根据用户所有觉得获取用户所有数据全选放入set集合
    在这里插入图片描述

    (5-6)set类型数据业务场景四(访问量统计去重)

    场景描述

    在这里插入图片描述

    解决方案

    针对不同的统计类型有不同的数据存储方式:
    (1)利用set集合的数据去重特征,记录各种访问数据
    (2)建立string类型数据,利用incr统计日访问量(PV)
    (3)建立set模型,记录不同cookie数量(UV)
    (4)建立set模型,记录不用IP数量(IP)

    (5-7)set类型数据业务场景五(黑白名单)

    场景描述

    在这里插入图片描述

    解决方案

    (1)基于经营战略设定问题用户发现、鉴别规则
    (2)周期性更行满足规则的用户黑名单,加入set集合
    (3)用户行为信息达到后与黑名单进行比比对,确认行为去向
    (4)黑名单过滤IP地址:应用于开放游客访问权限的信息源
    (5)黑名单过滤设备信息:应用于限定访问设备的信息源
    (6)黑名单过滤用户:应用于基于访问权限的信息源

    (6)Sorted Set:有序结合

    (6-1)基本信息

    (1)新的存储需求:根据排序有利于数据的有效显示,需要提供一种可以根据自身特征进行排序的方式。
    (2)需要的存储结构:新的存储模型,可以保存可排序的数据。
    (3)sorted_set类型:在set的存储结构基础上添加可排序字段。
    在这里插入图片描述score只存储其顺序。

    (6-2)常用命令

    ZADD key score1 member1 [score2 member2] 添加一个或多个成员到有序集合,或者如果它已经存在更新其分数
    ZCARD key 得到的有序集合成员的数量
    ZCOUNT key min max 计算一个有序集合成员与给定值范围内的分数
    ZREM key member [member ...] 从有序集合中删除一个或多个成员,不存在的成员将被忽略
    zrange key start stop [WITHSCORES]//按照从小到大的顺序,加上WITHSCORES,就会带上scores一起显示
    zrevrange key start stop [WITHSCORES]//按照从大到小的顺序
    
    zrangebyscore key min max [WITHSCORES] [LIMIT]   //查询scores在某个范围内的值
    zrevrangebyscore key max min [WITHSCORES]   //查询key某个索引范围内的值
    
    条件删除
    zremrangebyrank key start stop
    zremrangebyscore key min max
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    获取集合数据总量

    zcard key //获取总量
    zcount key min max //获取某一个范围的总量

    集合交、并存储操作

    zinterstore destination numkeys key [key …] //求和
    zunionstore destination numkeys key [key …]

    (6-3)注意

    (1)min与max用于限定搜索查询的条件
    (2)start与stop用于限定查询范围,作用于索引,表示开始和结束索引
    (3)offset与count用于限定查询范围,作用于查询结果,表示开始位置和数据总量

    (6-4)Sorted Set类型数据业务场景一(建立排序依据)

    场景描述

    在这里插入图片描述
    在这里插入图片描述

    解决方案

    (1)获取数据对应的索引(排名)

    zrank key member //正数第几位
    zrevrank key member //倒数第几位

    在这里插入图片描述

    (2)score 值获取与修改

    zscore key member //获取
    zincrby key increment member //score递增 increment

    注意事项

    (1)score 保存的数据存储空间是64位
    (2)score保存的数据也可以是一个双精度的double值,基于双精度浮点数的特征,可能会丢失精度,使用时侯要慎重
    (3)sorted_set底层存储还是基于set结构的,因此数据不能重复,如果重复添加相同的数据,score值将被反复覆盖,保留最后一次修改的结果

    (6-5)Sorted Set类型数据业务场景二(会员短期体验之过期失效)

    场景描述

    在这里插入图片描述

    解决方案

    (1)对于基于时间线限定的任务处理,将处理时间记录为score值,利用排序功能区分处理的先后顺序
    (2)记录下一个要处理的事件,当对比系统时间发现当然仍后到期后移除redis中的记录,并记录下一个要处理的时间
    (3)当新任务加入时,判定并更新当前下一个要处理的任务时间
    (4)为提升sorted_set的性能,通常将任务根据特征存储成若干个sorted_set.例如1小时内,1天内,年度等,操作时逐渐提升,将即将操作的若干个任务纳入到1小时内处理队列中
    (5)time命令获取当前系统时间

    (7)数据类型实践案例

    (7-1)按次调用-计数器

    场景描述

    在这里插入图片描述如何实现这个每分钟只能调用10次呢?

    解决方案

    (1)设计计数器,记录调用次数,用于控制业务执行次数。以用户id作为key,使用此时作为value
    (2)在调用前获取次数,判断是否超过限定次数,不超过次数的情况下,每次调用计数+1,业务调用失败,不递增
    (3)为了计数器设置生命周期为指定周期,例如10次/分钟,自动清空周期内使用次数。

    解决方案改良

    在这里插入图片描述
    利用可以存储的最大值是9223372036854775807,超过这个值就会抛出异常的特性。假如一分钟只能访问5次,可以将初始值设置为9223372036854775802,每次访问都加1,访问5次后这个数就会溢出异常。

    在这里插入图片描述

    (7-2)微信会话

    场景描述

    在这里插入图片描述

    解决方案

    (1)依赖list的数据具有顺序的特征对消息进行管理,将list结构作为栈使用
    对指定与普通会话分别创建独立的list分别管理
    (2)当某个list中接收到用户消息后,将消息发送方的id从list的一侧加入list(此处设定左侧)
    (3)多个相同id发出的消息反复入栈会出现问题,在入栈之前无论是否具有当前id对应得消息,先删除对应id
    (4)推送消息时先推送顶置会话list,再推送普通会话list,推送完成的list清除所有数据
    (5)消息的数量,也就是微信用户对话数量采用计数器的思想另行记录,伴随list操作同步更新

    (8)应用总结

    在这里插入图片描述

    (9) 准备工具类RedisUtil工具类,封装RedisTemplate这个类,便于对Redis的访问

    package com.how2java;
     
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
     
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.util.CollectionUtils;
     
    /**
     * 基于spring和redis的redisTemplate工具类
     * 针对所有的hash 都是以h开头的方法
     * 针对所有的Set 都是以s开头的方法                    不含通用方法
     * 针对所有的List 都是以l开头的方法
     */
    public class RedisUtil {
        private RedisTemplate<String, Object> redisTemplate;
         
        public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
            this.redisTemplate = redisTemplate;
        }
        //=============================common============================
        /**
         * 指定缓存失效时间
         * @param key 键
         * @param time 时间(秒)
         * @return
         */
        public boolean expire(String key,long time){
            try {
                if(time>0){
                    redisTemplate.expire(key, time, TimeUnit.SECONDS);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 根据key 获取过期时间
         * @param key 键 不能为null
         * @return 时间(秒) 返回0代表为永久有效
         */
        public long getExpire(String key){
            return redisTemplate.getExpire(key,TimeUnit.SECONDS);
        }
         
        /**
         * 判断key是否存在
         * @param key 键
         * @return true 存在 false不存在
         */
        public boolean hasKey(String key){
            try {
                return redisTemplate.hasKey(key);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 删除缓存
         * @param key 可以传一个值 或多个
         */
        @SuppressWarnings("unchecked")
        public void del(String ... key){
            if(key!=null&&key.length>0){
                if(key.length==1){
                    redisTemplate.delete(key[0]);
                }else{
                    redisTemplate.delete(CollectionUtils.arrayToList(key));
                }
            }
        }
         
        //============================String=============================
        /**
         * 普通缓存获取
         * @param key 键
         * @return 值
         */
        public Object get(String key){
            return key==null?null:redisTemplate.opsForValue().get(key);
        }
         
        /**
         * 普通缓存放入
         * @param key 键
         * @param value 值
         * @return true成功 false失败
         */
        public boolean set(String key,Object value) {
             try {
                redisTemplate.opsForValue().set(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
             
        }
         
        /**
         * 普通缓存放入并设置时间
         * @param key 键
         * @param value 值
         * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
         * @return true成功 false 失败
         */
        public boolean set(String key,Object value,long time){
            try {
                if(time>0){
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
                }else{
                    set(key, value);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 递增
         * @param key 键
         * @param by 要增加几(大于0)
         * @return
         */
        public long incr(String key, long delta){ 
            if(delta<0){
                throw new RuntimeException("递增因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, delta);
        }
         
        /**
         * 递减
         * @param key 键
         * @param by 要减少几(小于0)
         * @return
         */
        public long decr(String key, long delta){ 
            if(delta<0){
                throw new RuntimeException("递减因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, -delta); 
        } 
         
        //================================Map=================================
        /**
         * HashGet
         * @param key 键 不能为null
         * @param item 项 不能为null
         * @return 值
         */
        public Object hget(String key,String item){
            return redisTemplate.opsForHash().get(key, item);
        }
         
        /**
         * 获取hashKey对应的所有键值
         * @param key 键
         * @return 对应的多个键值
         */
        public Map<Object,Object> hmget(String key){
            return redisTemplate.opsForHash().entries(key);
        }
         
        /**
         * HashSet
         * @param key 键
         * @param map 对应多个键值
         * @return true 成功 false 失败
         */
        public boolean hmset(String key, Map<String,Object> map){ 
            try {
                redisTemplate.opsForHash().putAll(key, map);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * HashSet 并设置时间
         * @param key 键
         * @param map 对应多个键值
         * @param time 时间(秒)
         * @return true成功 false失败
         */
        public boolean hmset(String key, Map<String,Object> map, long time){ 
            try {
                redisTemplate.opsForHash().putAll(key, map);
                if(time>0){
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         * @param key 键
         * @param item 项
         * @param value 值
         * @return true 成功 false失败
         */
        public boolean hset(String key,String item,Object value) {
             try {
                redisTemplate.opsForHash().put(key, item, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         * @param key 键
         * @param item 项
         * @param value 值
         * @param time 时间(秒)  注意:如果已存在的hash表有时间,这里将会替换原有的时间
         * @return true 成功 false失败
         */
        public boolean hset(String key,String item,Object value,long time) {
             try {
                redisTemplate.opsForHash().put(key, item, value);
                if(time>0){
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 删除hash表中的值
         * @param key 键 不能为null
         * @param item 项 可以使多个 不能为null
         */
        public void hdel(String key, Object... item){ 
            redisTemplate.opsForHash().delete(key,item);
        }
         
        /**
         * 判断hash表中是否有该项的值
         * @param key 键 不能为null
         * @param item 项 不能为null
         * @return true 存在 false不存在
         */
        public boolean hHasKey(String key, String item){
            return redisTemplate.opsForHash().hasKey(key, item);
        }
         
        /**
         * hash递增 如果不存在,就会创建一个 并把新增后的值返回
         * @param key 键
         * @param item 项
         * @param by 要增加几(大于0)
         * @return
         */
        public double hincr(String key, String item,double by){ 
            return redisTemplate.opsForHash().increment(key, item, by);
        }
         
        /**
         * hash递减
         * @param key 键
         * @param item 项
         * @param by 要减少记(小于0)
         * @return
         */
        public double hdecr(String key, String item,double by){ 
            return redisTemplate.opsForHash().increment(key, item,-by); 
        } 
         
        //============================set=============================
        /**
         * 根据key获取Set中的所有值
         * @param key 键
         * @return
         */
        public Set<Object> sGet(String key){
            try {
                return redisTemplate.opsForSet().members(key);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
         
        /**
         * 根据value从一个set中查询,是否存在
         * @param key 键
         * @param value 值
         * @return true 存在 false不存在
         */
        public boolean sHasKey(String key,Object value){
            try {
                return redisTemplate.opsForSet().isMember(key, value);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 将数据放入set缓存
         * @param key 键
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSet(String key, Object...values) {
            try {
                return redisTemplate.opsForSet().add(key, values);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
         
        /**
         * 将set数据放入缓存
         * @param key 键
         * @param time 时间(秒)
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSetAndTime(String key,long time,Object...values) {
            try {
                Long count = redisTemplate.opsForSet().add(key, values);
                if(time>0) expire(key, time);
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
         
        /**
         * 获取set缓存的长度
         * @param key 键
         * @return
         */
        public long sGetSetSize(String key){
            try {
                return redisTemplate.opsForSet().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
         
        /**
         * 移除值为value的
         * @param key 键
         * @param values 值 可以是多个
         * @return 移除的个数
         */
        public long setRemove(String key, Object ...values) {
            try {
                Long count = redisTemplate.opsForSet().remove(key, values);
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        //===============================list=================================
         
        /**
         * 获取list缓存的内容
         * @param key 键
         * @param start 开始
         * @param end 结束  0 到 -1代表所有值
         * @return
         */
        public List<Object> lGet(String key,long start, long end){
            try {
                return redisTemplate.opsForList().range(key, start, end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
         
        /**
         * 获取list缓存的长度
         * @param key 键
         * @return
         */
        public long lGetListSize(String key){
            try {
                return redisTemplate.opsForList().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
         
        /**
         * 通过索引 获取list中的值
         * @param key 键
         * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
         * @return
         */
        public Object lGetIndex(String key,long index){
            try {
                return redisTemplate.opsForList().index(key, index);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
         
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
        public boolean lSet(String key, Object value) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
        public boolean lSet(String key, Object value, long time) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                if (time > 0) expire(key, time);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
        public boolean lSet(String key, List<Object> value) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
        public boolean lSet(String key, List<Object> value, long time) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                if (time > 0) expire(key, time);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 根据索引修改list中的某条数据
         * @param key 键
         * @param index 索引
         * @param value 值
         * @return
         */
        public boolean lUpdateIndex(String key, long index,Object value) {
            try {
                redisTemplate.opsForList().set(key, index, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         
        /**
         * 移除N个值为value
         * @param key 键
         * @param count 移除多少个
         * @param value 值
         * @return 移除的个数
         */
        public long lRemove(String key,long count,Object value) {
            try {
                Long remove = redisTemplate.opsForList().remove(key, count, value);
                return remove;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
         
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
  • 相关阅读:
    Caché数据库及其特性
    Linux高负载排查最佳实践
    linux安装elasticsearch-head (es可视化界面)
    【SA8295P 源码分析 (二)】46 - OpenWFD Server 启动流程 之 /dev/openwfd_server_0 管道事务源码分析
    Window部署Jaeger
    机器学习中的线性回归——基于R
    【代码】Android|获取压力传感器、屏幕压感数据(大气压、原生和Processing)
    三年之约!亚马逊联手哈佛大学倾力打造量子互联网
    8/3 训练日志 (树状数组+区间覆盖+思维+01字典树)
    Visual Studio运行Python程序(超级详细)
  • 原文地址:https://blog.csdn.net/weixin_44823875/article/details/125451507