Redis五种数据类型及使用场景详解

我们都知道Redis支持5种不同的数据类型、但是在我们的日常开发过程中,用的最多的是String类型。当存一个字段属性时,我们使用String,当存储一个对象时,我们使用Gson转换成一个Json字符串去存储。但是针对Redis的五种数据类型,有很多业内的一些常用的使用场景整理。

1、String类型

   常用指令汇总:

  • 添加数据:set key value
  • 获取数据:get key
  • 删除数据:del key
  • 添加多个数据:mset key1 valueq key2 value2 …
  • 获取多个数据:mget key1 key2 ...
  • 获取数据字符个数(字符串长度)strlen key
  • 追加信息到原始信息后部(如果原始信息存在就追加,否则新建)append key value

 业务场景使用: 

    1.自增主键,例如MySQL的自增主键获取、  

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

     2. String时效性处理

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

解决方案:  

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

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

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

String类型使用注意事项:

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

2、Hash数据类型 

     概述: 

        如果说String类型,一个Key对应一个对象的字段,那么使用Hash就可以存储整个对象,当然这个存储的键值对是有上限的。合理的使用Hash类型,可以避免没必要的内存消耗。其中对象的字段名为Filed,属性为Value,其中Value只能存储String类型。

     常用指令汇总:

  •  添加修改数据:hset key field value
  •  获取数据:hget key field hgetall key
  •  删除数据: hdel key field1 [field2]
  •  添加多个数据:hmset key field1 value1 field2 calue2
  •  获取多个数据:hget key field1 field2...
  •  获取Hash表中的数量:hlen key
  •  获取哈希表中是否存在指定的字段:hexists key field
  • 获取哈希表中所有的字段名和字段值:hkeys key //字段名  hvals key //字段值

  • 设置指定字段的数值数据增加指定范围的值:hincrby key field increment        hincrbyfloat key field increment

业务场景使用 

    1.电商网站购物车的设计与实现。

     购物车的缓存,我们使用淘宝时,还是比较常用到购物车页面,需要对购物车数据进行缓存的案例就可以用到Hash类型。其中,将用户Id:作为Key。商品Id作为Field字段,数量作为Value信息。

    具体的解决方案:

  •  以客户Id作为Key。将购物车中所有的信息Hash存储,不同的商品ID对应不同的Field。
  •  将商品ID作为feild,购买数量做为Value存储
  •  添加商品,在hash中追加不同的feild。
  •  更改数量: 自增/自减 更改Value值

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

每条购物车中的商品记录保存成两条field

field1 专用于保存购买数量
1、命名格式:商品id:nums 
2、保存数据:数值

field2 专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等等
1、命名格式:商品id:info
2、保存数据:json
 

  2.抢购、激活码、限时发放优惠券等场景的应用

   案例分析:

      例如双11期间。商家做活动,限时发放优惠卷。有30、50、100面额的优惠券各100张

  具体的解决方案:

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

Has类型使用注意事项: 

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

3、List数据类型  

       概述:

          List数据类型类似于Java中LinkedList的数据结构,是一个双向的链表结构,支持从头部或者尾部添加或者删除数据。 也类似于Java栈,对于进入list中的数据,有严格的顺序FIFO,先进先出。

     常用指令汇总:

  • 添加/修改数据: lpush key value1 [value2] 从list左边插入数据                                                                             rpush key value1 [value2] 从list右边插入数据  
  •  获取数据:lrange key start stop //获取从左数第start到stop个元素,从0开始
                       lindex key index //查询第i个元素
                       llen key //list的长度
  • 获取并移除数据:lpop key //获取并删除左边第一个元素
                                 rpop key //获取并删除右边第一个元素
  • 规定时间内获取并移除数据:blpop key1 [key2] timeout
                                                   brpop key1 [key2] timeout

    业务场景使用 

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

         解决方案:移除制定的数据:

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

       2.业务场景-最新消息的展示

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

     具体解决方案:

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

 List类型数据操作注意事项

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

4、Set数据类型 

   概述:

Set类型类似Java中HashSet。与Hash类型的存储结构一致,唯一的区别在于、Set只存储key值,即只保留feild,其中最重要的属性就是不允许有重复feild存在。

  常用指令汇总:

  •    添加数据: sadd key menber1 [member2]
  •    获取全部数据:smembers key
  •    删除数据:srem key member1 [member2]
  •    获取集合数据总量:scard key
  • 判断集合中是否包含指定数据 sismember key member

  业务场景使用

    1.随机操作数据

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

业务分析

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

解决方案

  • 随机获取集合中指定数量的数据 srandmember key [count

2.业务场景-共同好友

解决方案

  • 求两个集合的交、并、差集

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

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

sinterstore destination key1 [key2]
sunionstore destination key1 [key2]
sdiffstore destination key1 [key2] 

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

 smove source destination member

3.业务场景-同类型不重复数据的合并操作 

解决方案

依赖set集合数据不重复的特征,依赖set集合hash存储结构特征完成数据过滤与快速查询

  • 根据用户id获取用户所有角色
  • 根据用户所有角色获取用户所有操作权限放入set集合
  • 根据用户所有觉得获取用户所有数据全选放入set集合

4.set业务场景-访问量统计去重 

解决方案

针对不同的统计类型有不同的数据存储方式:

  • 利用set集合的数据去重特征,记录各种访问数据
  • 建立string类型数据,利用incr统计日访问量(PV)
  • 建立set模型,记录不同cookie数量(UV)
  • 建立set模型,记录不用IP数量(IP)

5、set业务场景-黑白名单 

 解决方案

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

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

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

5、sorted_set类型 

  概述:

sorted_set其实就是一张有序的Set类型,我可以利用有序这个特性,来合理的使用、

  常用指令汇总:

  •   添加数据:zadd key score1 member1 [score2 member2] 
  •   获取全部数据:zrange key start stop [WITHSCORES]//按照从小到大的顺序,加上               WITHSCORES,就会带上scores一起显示
                             zrevrange key start stop [WITHSCORES]//按照从大到小的顺序
  •   删除数据:zrem key member [member …]
  •   按条件获取数据://查询scores在某个范围内的值 zrangebyscore key min max [WITHSCORES] [LIMIT] //查询key某个索引范围内的值 zrevrangebyscore key max min [WITHSCORES]

   业务场景分析:

      1.业务场景- 建立排序依据

解决方案

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

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

  • score 值获取与修改

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

 2.业务场景-会员短期体验之过期失效

解决方案

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

6.五种类似数据的总结

Redis五种数据类型及使用场景详解_第1张图片

Redis的应用场景

总结一

计数器

可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。

缓存

将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。

会话缓存

可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。

全页缓存(FPC)

除基本的会话token之外,Redis还提供很简便的FPC平台。以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。

查找表

例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠的数据来源。

消息队列(发布/订阅功能)

List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。

分布式锁实现

在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。

其它

Set 可以实现交集、并集等操作,从而实现共同好友等功能。ZSet 可以实现有序性操作,从而实现排行榜等功能。

总结二

Redis相比其他缓存,有一个非常大的优势,就是支持多种数据类型。

数据类型说明string字符串,最简单的k-v存储hashhash格式,value为field和value,适合ID-Detail这样的场景。list简单的list,顺序列表,支持首位或者末尾插入数据set无序list,查找速度快,适合交集、并集、差集处理sorted set有序的set

其实,通过上面的数据类型的特性,基本就能想到合适的应用场景了。

string——适合最简单的k-v存储,

类似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。

hash——一般key为ID或者唯一标示,

value对应的就是详情了。如商品详情,个人信息详情,新闻详情等。

list——因为list是有序的,

比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等。

set——可以简单的理解为ID-List的模式,

如微博中一个人有哪些好友,set最牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人共同的好友等。

Sorted Set——是set的增强版本,

增加了一个score参数,自动会根据score的值进行排序。比较适合类似于top 10等不根据插入的时间来排序的数据。

如上所述,虽然Redis不像关系数据库那么复杂的数据结构,但是,也能适合很多场景,比一般的缓存数据结构要多。了解每种数据结构适合的业务场景,不仅有利于提升开发效率,也能有效利用Redis的性能。
 

参考文章:

https://blog.csdn.net/zzu_seu/article/details/106323114

https://blog.csdn.net/ThinkWon/article/details/103522351

注:文中所有的应用场景都截取于上篇博客。在加上一点自己的理解。

        

你可能感兴趣的:(Redis,redis)