Redis-核心数据结构&IO多路复用

  • 五种数据结构:string hash list set zset
    • 应用场景
  • RedisTemplate 默认采用的是JDK的序列化,直接看的话key会有乱码,建议用 StringRedisTemplate
  • IO多路复用
  • SCAN
redisTemplate.opsForValue();   //操作字符串
redisTemplate.opsForHash();    //操作hash
redisTemplate.opsForList();    //操作list
redisTemplate.opsForSet();     //操作set
redisTemplate.opsForZSet();    //操作有序set

数据结构

命令参数含义代码
STRINGSTRINGRedisTemplate rt
SETkey value存入字符串键值对rt.opsForValue().set(“key”,“value”)
MSETkey value [key value …]批量存入字符串键值对
SETNXkey value存入一个不存在的字符串键值对
GETkey获取字符串键值rt.opsForValue().get(“key”)
MGETkey [key …]批量获取字符串键值
DELkey [key …]删除一个键rt.delete(“key”)
EXPIREkey seconds设置一个键的过期时间(秒)
INCRkey原子 +1
DECRkey原子 -1
INCRBYkey num原子 +num
DECRBYkey num原子 -num
STRLENkeyrt.opsForValue().size(“key”)
GETSETkey valuert.opsForValue().getAndSet(“key”,“value”)
GETRANGEkey start endrt.opsForValue().get(“key”,start,end)
APPENDkey valuert.opsForValue().append(“key”,“value”)
HASHHASH
HSETkey field value存入一个哈希表key的键值rt.opsForHash().put(“key”,“field”,“value”)
HSETNXkey field value存入一个不存在的哈希表key的键值rt.opsForHash().putIfAbsent(“key”,“field”,“value”)
HMSETkey field value [field value …]在一个哈希表key中存入多个键值对rt.opsForHash().putAll(“key”,map)
HGETkey field获取哈希表key对应的field键值rt.opsForHash().get(“key”,“field”)
HMGETkey field [field …]批量获取哈希表key中多个field键值rt.opsForHash().multiGet(“key”,fieldList)
HDELkey field [field …]删除哈希表key中的field键值rt.opsForHash().delete(“key”,“field1”,“field2”)
HLENkey返回哈希表key中field的数量
HGETALLkey返回哈希表key中所有的键值rt.opsForHash().entries(“key”)
HINCRBYkey field num为哈希表key中field键的值原子 +num
HEXISTSkey fieldrt.opsForHash().hasKey(“key”,“field”)
HVALSkeyrt.opsForHash().values(“key”)
HKEYSkeyrt.opsForHash().keys(“key”)
LISTLIST
LPUSHkey value [value …]插入到列表的表头(最左边)rt.opsForList().leftPush(“key”,“value”)

rt.opsForList().leftPushAll(“key”,valueList)
RPUSHkey value [value …]插入到列表的表尾(最右边)rt.opsForList().rightPush(“key”,“value”)

rt.opsForList().rightPushAll(“key”,valueList)
LPOPkey移除并返回key列表的头元素rt.opsForList().leftPop(“key”)
RPOPkey移除并返回key列表的尾元素rt.opsForList().rightPop(“key”)
LRANGEkey start stop返回列表key中 start-stop 区间内的元素rt.opsForList().range(“key”,start,end)
BLPOPkey [key …] timeout从列表表头弹出一个元素,若没有则阻塞等待timeout秒,如果timeout=0,则一直等待
BRPOPkey [key …] timeout从列表表尾弹出一个元素,若没有则阻塞等待timeout秒,如果timeout=0,则一直等待
LINDEXkey indexrt.opsForList().index(“key”, index)
LLENkeyrt.opsForList().size(“key”)
LPUSHXlist nodert.opsForList().leftPushIfPresent(“list”,“node”)
RPUSHXlist nodert.opsForList().rightPushIfPresent(“list”,“node”)
LREMlist count valuert.opsForList().remove(“list”,count,“value”)
LSETkey index valuert.opsForList().set(“list”,index,“value”)
SETSET
SADDkey member [member …]往集合key中存入元素,元素存在则忽略rt.boundSetOps(“key”).add(“member1”,…)

rt.opsForSet().add(“key”, set)
SREMkey member [member …]从集合key中删除元素rt.opsForSet().remove(“key”,“member1”,…)
SMEMBERSkey获取集合key中所有元素rt.opsForSet().members(“key”)
SCARDkey获取集合key的元素个数rt.opsForSet().size(“key”)
SISMEMBERkey member判断member元素是否存在于集合key中rt.opsForSet().isMember(“key”,“member”)
SRANDMEMBERkey [count]从集合key中选出count个元素,元素不从key中删除rt.opsForSet().randomMember(“key”,count)
SPOPkey [count]从集合key中选出count个元素,元素从key中删除rt.opsForSet().pop(“key”)
SINTERkey [key …]交集运算rt.opsForSet().intersect(“key1”,“key2”)
SINTERSTOREdestination key [key …]将交集结果存入新集合destination中rt.opsForSet().intersectAndStore(“key1”,“key2”,“des”)
SUNIONkey [key …]并集运算rt.opsForSet().union(“key1”,“key2”)
SUNIONSTOREdestination key [key …]将并集结果存入新集合destination中rt.opsForSet().unionAndStore(“key1”,“key2”,“des”)
SDIFFkey [key …]差集运算rt.opsForSet().difference(“key1”,“key2”)
SDIFFSTOREdestination key [key …]将差集结果存入新集合destination中rt.opsForSet().differenceAndStore(“key1”,“key2”,“des”)
ZSETZSET
ZADDkey score member [[score member]…]往有序集合key中加入带分值元素
ZREMkey member [member …]从有序集合key中删除元素
ZSCOREkey member返回有序集合key中元素member的分值
ZINCRBYkey num member为有序集合key中元素member的分值原子 +num
ZCARDkey返回有序集合key中元素个数
ZRANGEkey start stop [WITHSCORES]正序获取有序集合key从start下标到stop下标的元素
ZREVRANGEkey start stop [WITHSCORES]倒序获取有序集合key从start下标到stop下标的元素
ZUNIONSTOREdestkey numkeys key [key …]并集计算
ZINTERSTOREdestkey numkeys key [key …]交集计算

应用场景

  • STRING 应用场景

    • 单值缓存 | 对象缓存(Session共享)
    • 分布式锁:SET product:10001 true ex 10 nx
    • 计数器(分布式唯一ID,客户端批量获取,缺点:断电导致重复ID)
  • HASH 应用场景

    • 对象缓存(大KEY问题)
    • 购物车:用户id为key;商品id为field;商品数量为value
    • 优点
      • 同类数据归类整合储存,方便数据管理
      • 相比string操作消耗内存与cpu更小
      • 相比string储存更节省空间
    • 缺点
      • 过期功能不能使用在field上,只能用在key上
      • Redis集群架构下不适合大规模使用
  • LIST 应用场景

    • 社交平台发文(时间顺序展示)
    • 数据结构
      • 栈 = LPUSH + LPOP
      • 队列 = LPUSH + RPOP
      • 阻塞队列 = LPUSH + BRPOP
  • SET 应用场景

    • 抽奖:SADD / SRANDMEMBER / SPOP / SMEMBERS
    • 点赞:SADD / SREM / SISMEMBER / SMEMBERS / SCARD / SINTER
    • 关注模型
      • 共同关注:SINTER
      • 我关注的人也关注他:SISMEMBER
      • 可能认识的人(朋友的朋友 - 我的朋友):SDIFF
    • 商品筛选(多查询条件取交集):SINTER
  • ZSET 应用场景

    • 新闻排行榜
      • 点击:ZINCRBY hotNews:20190819 1 xxx文章
      • 前十:ZREVRANGE hotNews:20190819 0 9 WITHSCORES
      • 七日榜单:ZUNIONSTORE hotNews:20190813-20190819 7
      • 七日前十:ZREVRANGE hotNews:20190813-20190819 0 9 WITHSCORES

IO多路复用

  • 单线程:
    • Redis 的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的
    • 因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用耗时的指令(比如keys),一不小心就可能会导致 Redis 卡顿
  • Redis的IO多路复用:
    • redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器
  • 查看redis支持的最大连接数,在redis.conf文件中可修改:CONFIG GET maxclients
  • SCAN
    • KEYS是全量遍历,当数据量大时,性能很差,应用 SCAN 取代(手动分段遍历,直到游标为0停止遍历)
    • SCAN 0 match jxch** count 100
      • 以0为游标,分段扫描以jxch开头的key,每次返回100个,然后以返回值为游标,继续扫描,直到返回的游标为0
      • 注意,100是个参考值,实际返回的是接近100的数目,可能多也可能少(取决于HASH桶中有几个值,因为Redis的存储结构是哈希表)
    • 如果在scan的过程中如果有键的变化(增加、 删除、 修改) ,那么遍历效果可能会碰到如下问题
      • 新增的键可能没有遍历到(不会扫描已经遍历过的HASH桶)
      • 遍历出了重复的键(发生了RE-HASH)
    • SCAN并不能保证完整的遍历出来所有的键, 这些是我们在开发时需要考虑的,但在追求性能的情况下,往往并不要求一致性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值