redis五种数据类型

一、String

可以存图片,数字等。做递增递减操作都行

二、list类型

redis的list是用的是双端链表来实现的,两边口都可以进出。使用列表的技巧如下:

list的value允许重复,所以存有重复值的可以考虑用这个。还有就是有人发布微博,展示新的列表信息可以用这个,这里面的lrange就提供了这个功能。

业务一:涉及到消息队列的时候用到的命令

场景:生产者生产了10个消息,消费者去拿消息,拿到第10个后,继续去拿第11个。发现没有了,这个时候应该怎么处理呢?

我:可以用阻塞队列,就比如lpush+brpop可用于消息队列(注:对于阻塞来说,是没有brpush之类的,只有pop因为它只是拿)
之所以用到这个是因为,我去拿第11个,没拿到如果用了阻塞有消息了就会知道消费者。如果不用阻塞,拿第11个,没了就是没了,再有消息也不会来通知你。所以这个适合用来做消息队列,跟RabbitMq挺像的,具体用哪个需要根据业务来说,如果对于数据一致性不是那么高的可以用list这个。
因为RabbitMq是通过一个保证数据一致性,如果没必要就不需要引入RabbtiMq,原因如下:
引入中间件,需要一定的维护成本,且增加了系统的复杂度

对于消息队列的补充说明:redis的发布订阅模式,也就相当于rabbitmq的作用消息队列,发布和订阅消息嘛,但如果用redis的发布订阅来实现是不可靠的,它也不支持ack。所以redis实现的消息队列不能保证消息的可靠性,除非自己实现消息确认机制,但这太麻烦了。

业务二:栈
  因为列表存储的是有序字符串,满足队列的特点,也就能满足栈先进先出的特点,

三、hash

1,介绍
  1)使用hash存储会比字符串更加方便直观,是一个string类型的key,value的映射表。特别适合用于存储对象。
  2)比较直观,相比string更节省空间,
命令如下:
在这里插入图片描述

2,应用场景

2.1 购物车
以用户id为key,商品id为field,商品数量为value。恰好构成了购物车的3个要素

2.2 存储对象

2.2.1 说到string+json来存储对象还是hash

hash类型的结构与对象的结构相似,也可以用来存储对象。
补充说明:在介绍string类型的应用场景有所介绍,string+json也是存储对象的一种方式,思考:存储对象时,到底用string+json还是用hash呢?
两种方式的对比如下:从效率、容量、灵活性、序列化来说

2.2.2 如何选择用string+json来存储对象还是hash呢?
当对象的某个属性需要频繁修改时,不适合用string+json,因为它不够灵活,每次修改都需要重新将整个对象序列化并赋值。
1)推荐使用hash的场景:
如果使用hash,则可以针对某个属性单独修改,没有序列化,也不需要修改整个对象。比如:商品的价格、销量、关注数、评论数等可能进场发生变化的属性,就适合存储在hash类型里。
当然不常变化的属性存储在hash类型里也没有问题,比如商品名称、商品描述、上市日期等。
2)推荐使用string+json的场景
比如,商品的标签是一个标签对象的列表,商品可领取的优惠券是一个优惠券对象的列表。所以value想存储优惠券对象还是要使用json来序列化,这样的话序列化工作就太繁琐了。不如直接用string+json的方式存储商品信息来的简单。

总结:一般对象用string+json存储,对象中某些频繁变化的属性抽出来的用hash存储。

hash的一些命令地址

2.2.3 对进行序列化的一些思考
1)为什么要进行序列化
  如果你的数据想要持久化就需要序列化,如果你的对象没实现序列化怎么才能进行持久化和网络传输呢?要持久化和网络传输就的转为字节流,所以在分布式系统和设计数据持久化的场景中,你就得实现序列化。
2)是不是每个bean都要序列化?
  看你的数据是否要持久化与及是否要传输给另一个应用了,没有的话就不许哟啊。如:我们用fastjson将实体类转化成json字符串时,并不涉及到字节流,所以跟序列化没关系。
  有时候发现没有序列化,依然可以持久化到数据库,这个其实是因为实体类张红常用的数据类型,如Date、String等等,他们已经实现了序列化。而一些基本类型,数据库里面有与之对应的数据结构,我们没有实现serializabel接口,但其实在声明各个不同变量的时候,由具体的数据类型帮助我们实现了序列化操作。
  (重点)在nosql中,并没有与我们java基本类型对应的数据结构,所以进行存储时,必须将对象进行序列化。

四、set无序集合

1,定义
redis的set是String类型的无序集合,跟list列表一样也是可以保存多个字符串元素的,与列表不同的是,集合中不允许有重复元素并且集合中的元素时无序的。
集合的成员是唯一的,意味着集合中不能出现重复的数据。
2,操作命名
sadd:向集合中添加一个或多个成员
scard:获取集合的成员数
smemeber:获取集合中的所有成员
sismember:判断member元素是否是集合key的成员

3,应用场景
3.1 用户标签,寻找共同兴趣的人
一个用户对篮球,足球感兴趣;另一个用户对橄榄球、乒乓球感兴趣,这些兴趣就是一个标签。可以通过这个标签去寻找喜欢同一个标签的人。
用法:两个步骤,给用户打标签和在标签里添加用户
  1)给用户打标签:sadd user:1:tags tag1 tag2
  2)标签里添加用户:sadd tag1:users user:1 sadd tag2:users user:1
使用sinter交集求出两个user共同标签:sinter user:1:tags user:2:tags

3.2 抽奖功能
redis集合中两个命令支持获取随机数,分别是srandmember 和spop
应用场景:
1)京东京豆的抽奖用的是srandmember,这个特点是抽5京豆还可以再抽到5京豆,即京豆是无限量抽
2)支付宝抽奖:奖品不能重复抽,用spop。特别是已经抽过了的就立马弹出删除,这样可以保证已经抽过奖的不能再进行抽奖了。
如下代码所示:

@RestController
@RequestMapping("/api/zfb")
public class ZFBController {

    @Autowired
    private RedisTemplate redisTemplate;
    
    /**
     * 抽奖接口
     * @param num 代表有几台奖品
     * @return
     */
    @GetMapping("/prize2")
    public List<Integer> prize2(int num) {
        SetOperations<String, Integer> setOperations = redisTemplate.opsForSet();
        // 随机返回并删除Set中的一个元素,从redis中随机寻找一个用户,返回并在redis中将其删除
        List<Integer> objs = setOperations.pop(JdTask.PRIZE_ZFB_KEY, num);
        return objs;
    }
}

五、zset有序集合

1,介绍
  成员是唯一的,但分数是可以重复的,zset是通过分数来为集合中的成员进行从小到大的排序。集合是通过哈希来实现的,所以添加删除查找的复杂度都是0(1)
命令如下:
  zadd:将一个带有给定分支的添加到有序集合里面
  zrange:从有序集合中获取更多个元素
  zrem:如果给定元素存在有序集合中,就移除这个元素

2,应用场景

场景一:排行榜

  比如查出给某人发的微博点在数前三名的

场景二:延迟消息队列
  下单操作,固定在15分钟内进行支付,如果超过了15分钟则自动取消订单。
用redis中的zset可以完成这个功能,用法如下:
  将下单后的十五分钟后时间作为score,订单为value存入redis,消费者轮询去消费,如果消费的时间大于score,则使用ZREM命令将这笔记录移除队列,取消订单。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值