Redis在项目中的地位及使用场景剖析

一、 redis 特点

  • 所有数据存储在内存中,高速读写

  • 提供丰富多样的数据类型:string、 hash、 set、 sorted set、bitmap、hyperloglog

  • 提供了 AOF 和 RDB 两种数据的持久化保存方式,保证了 Redis 重启后数据不丢失

  • Redis 的所有操作都是原子性的,还支持对几个操作合并后的原子性操作,支持事务

 通常我们都把数据存到关系型数据库中,但为了提升应用的性能,我们应该把访频率高且不会经常变动的数据缓存到内存中。。Redis 没有像 MySQL 这类关系型数据库那样强大的查询功能,需要考虑如何把关系型数据库中的数据,合理的对应到缓存的 key-value 数据结构中。

二、 设计 Redis Key

分段设计法

  使用冒号把 key 中要表达的多种含义分开表示,步骤如下:

  1. 把表名转化为 key 前缀

  2. 主键名(或其他常用于搜索的字段)

  3. 主键值

  4. 要存储的字段。

eg. 用户表(user)

id name email
1 zj 1234@163.com
2 ai 1234@163.com

这个简单的表可能经常会有这个的需求:>根据用户 id 查询用户邮箱地址,可以选择把邮箱地址这个数据存到 redis 中:

set user:id:1:email 1234@163.com;
set user:id:2:email 1234@163.com;

三、 String数据类型的应用场景

1. 简介

  string 类型是 Redis 中最基本的数据类型,最常用的数据类型,甚至被很多玩家当成 redis 唯一的数据类型去使用。string 类型在 redis 中是二进制安全(binary safe)的,这意味着 string 值关心二进制的字符串,不关心具体格式,你可以用它存储 json 格式或 JPEG 图片格式的字符串。   

2. 数据模型

  string 类型是基本的 Key-Value 结构,Key 是某个数据在 Redis 中的唯一标识,Value 是具体的数据。

Key Value
‘name’ ‘redis’
‘type’ ‘string’

3. 应用场景

(1) 存储 MySQL 中某个字段的值

把 key 设计为 表名:主键名:主键值:字段名 eg.

set user:id:1:email 10000@qq.com

(2) 存储对象

string 类型支持任何格式的字符串,应用最多的就是存储 json 或其他对象格式化的字符串。(这种场景下推荐使用 hash 数据类型)

set user:id:1 '[{"id":1,"name":"zj","email":"10000@qq.com"},{"id":1,"name":"zj","email":"10000@qq.com"}]'

(3) 生成自增 id

当 redis 的 string 类型的值为整数形式时,redis 可以把它当做是整数一样进行自增(incr)自减(decr)操作。由于 redis 所有的操作都是原子性的,所以不必担心多客户端连接时可能出现的事务问题。

incr 对值进行加1操作,如果不是整数,返回错误,如果不存在按照从0开始 decr 同incr,但是是减1操作 incrby,decrby ,增加减去指定的数

(4) 生成自增 id

比如视频播放次数,点赞次数。

(5)共享session

数据共享的功能,redis作为单独的应用软件用来存储一些共享数据供多个实例访问。

(6)自动定时过期

set key value [ex seconds] [px millseconds] [nx|xx]

ex seconds: 键过期时间

px milliseconds: 为键设置毫秒级过期时间

nx: 键必须不存在才可以设置成功,用于添加

xx: 键必须存在,才可以设置成功,用于更新

(7)批量操作

mset,mget

批量设置和获取命令,在操作多个key的时候可以节省网络传输时间

mset key value [key value...]
mget key [key ...]

四、hash 数据类型的应用场景

1. 简介

  hash 类型很像一个关系型数据库的数据表,hash 的 Key 是一个唯一值,Value 部分是一个 hashmap 的结构。

2. 数据模型

  假设有一张数据库表如下:

id name type
1 redis hash

  如果要用 redis 的 hash 结构存储,数据模型如下:

  hash数据类型在存储上述类型的数据时具有比 string 类型更灵活、更快的优势,具体的说,使用 string 类型存储,必然需要转换和解析 json 格式的字符串,即便不需要转换,在内存开销方面,还是 hash 占优势。 和字符串很像,基本上redis对字符串操作的命令,Redis的Hash一般也存在,不过在命令前多个一个h。   

3. 应用场景

hash 类型十分适合存储对象类数据,相对于在 string 中介绍的把对象转化为 json 字符串存储,hash 的结构可以任意添加或删除‘字段名’,更加高效灵活。 一些关系型数据库中不是特别复杂的表,也无需复杂的关系查询,可以使用Redis的Hash来存储,也可以用Hash做表数据缓存。

hmset user:1 name zj email 123456@163.com
​
hset key field value
hsetnx key field value  //与setnx命令一样,不存在则设置值,用于添加,作用在field上面
​
hget key field //获取值
hdel key field // 删除值
hlen key //子酸field的个数
hmset key field value [filed value] //批量设置field-value
hexists key field  //判断filed是否存在
hkeys key //获取所有的field
hvals key //获取所有的value
hgetall key //获取所有的field-value ,如果元素数较多会存在阻塞redis的可能
hincreby key filed

五、list 数据类型的应用场景

1. 简介

  list 是按照插入顺序排序的字符串链表,可以在头部和尾部插入新的元素(双向链表实现,两端添加元素的时间复杂度为 O(1))。插入元素时,如果 key 不存在,redis 会为该 key 创建一个新的链表,如果链表中所有的元素都被移除,该 key 也会从 redis 中移除。

2. 数据模型

  列表用来存储多个有序的字符串,一个列表最多可以存储2^32 - 1个元素,在redis中可以对列表的两端插入push和弹出pop,还可以取指定范围的元素。常见操作时用 lpush 命令在 list 头部插入元素, 用 rpop 命令在 list 尾取出数据。

rpush key value [value...] //从右插入元素
lpush key value [value...] //从左边插入元素
​
lrange key start end //获取指定范围的元素列表
lindex key index  //获取列表指定索引下标的元素
​
llen key  //获取列表的长度
​
lpop key // 从列表左侧弹出元素
rpop key // 从列表右侧弹出元素
lrem key count value //从列表中找到等于value的元素,并进行删除,根据count的不同有不同的情况
lset key index newValue //修改指定索引下标的元素
blpop key timeout  //阻塞式左弹出key
brpop key timeout  //阻塞式右弹出key

3. 应用场景

(1) 消息队列

redis 的 list 数据类型对于大部分使用者来说,是实现队列服务的最经济,最简单的方式。我司使用redis做消息队列,lpush + brpop或rpop命令,实现先进先出,如果消费失败客户端把key再放回去,消费成功就remove掉。

(2) “最新内容”

因为 list 结构的数据查询两端附近的数据性能非常好,所以适合一些需要获取最新数据的场景,比如新闻类应用的 “最近新闻”。

4.优化建议

(1) list 是链表结构,所有如果在头部和尾部插入数据,性能会非常高,不受链表长度的影响;但如果在链表中插入数据,性能就会越来越差。

5.使用口诀:

lpush + lpop 栈 lpush + rpop 队列 lpush + ltrim = 有限集合 lpush + brpop = 消息队列

六、set 数据类型的应用场景

1. 简介

  set 数据类型是一个集合(没有排序,不重复),可以对 set 类型的数据进行添加、删除、判断是否存在等操作(时间复杂度是 O(1) )   set 集合不允许数据重复,如果添加的数据在 set 中已经存在,将只保留一份。   set 类型提供了多个 set 之间的聚合运算,如求交、并、差集,这些操作在 redis 内部完成,效率很高。

2. 数据模型

sadd key value [value...] //添加元素
srem key value [value...] //删除元素
scard key   //计算元素的个数
sismember key value //判断元素是否在集合中
srandmember key [count]  //随机从集合中返回指定个数的元素,不写默认为1
spop key //从集合随机取出元素
smembers key //获取集合内的所有元素
​
sinter key1 key2 //求集合的交集
sunion key1 key2 //求集合的并集
sdiff key1 key2  //求集合的差集

3. 应用场景

  set 类型的特点是——不重复且无序的一组数据,并且具有丰富的计算功能,在一些特定的场景中可以高效的解决一般关系型数据库不方便做的工作。

(1)“共同好友列表”

  社交类应用中,获取两个人或多个人的共同好友,两个人或多个人共同关注的微博这样类似的功能,用 MySQL 的话操作很复杂,可以把每个人的好友 id 存到集合中,获取共同好友的操作就可以简单到一个取交集的命令就搞定。

// 这里为了方便阅读,把 id 替换成姓名
sadd user:wade james melo paul kobe
sadd user:james wade melo paul kobe
sadd user:paul wade james melo kobe
sadd user:melo wade james paul kobe
​
// 获取 wade 和 james 的共同好友
sinter user:wade user:james
/* 输出:*      1) "kobe"*      2) "paul"*      3) "melo"*/// 获取香蕉四兄弟的共同好友sinter user:wade user:james user:paul user:melo/* 输出:*      1) "kobe"*//*类似的需求还有很多 , 必须把每个标签下的文章 id 存到集合中,可以很容易的求出几个不同标签下的共同文章;把每个人的爱好存到集合中,可以很容易的求出几个人的共同爱好。 */

(2)唯一ip

跟踪一些具有唯一性的一些数据,比如访问某一博客的唯一ip地址的信息,我们仅需要在每次访问的时候,将ip存入redis中。利用服务器端聚合操作方便高效的特性,维护数据对象之间的关联关系。

七、sorted set 数据类型的应用场景

1.简介

  在 set 的基础上给集合中每个元素关联了一个分数,往有序集合中插入数据时会自动根据这个分数排序。它保留了元素不能重复的特性,并且元素是有序的。

2.基本操作

zadd key score member  //score是可以重复的,添加key的时候指定分数
zcard key //计算成员个数
zscore key member //计算某个成员的分数
zrank key member //计算成员排名,从低到高
zrevrank key member //计算成员排名,从高到低
zrem key member [member...]  //删除成员
zincrby key increnment member //增加成员的分数
zrange key start end [withscores]  //从低到高返回指定排名的分数
zrevrange key start end [withscores]  //从高到低返回
​
zrangebyscore key min max [withscores] [limit offset count] //按照分数从低到高返回
zrevrange score  key min max [withscores] [limit offset count] //按照分数从高到低返回成员
​
withscore 代表返回的时候带上成员的分数
​
...还有求交集,并集等操作

3.应用场景

  在集合类型的场景上加入排序就是有序集合的应用场景了。

(1)根据好友的“亲密度”排序显示好友列表。

// 用元素的分数(score)表示与好友的亲密度
zadd user:kobe 80 james 90 wade  85 melo  90 paul
​
// 根据“亲密度”给好友排序
zrevrange user:kobe 0 -1
​
/*** 输出:*      1) "wade"*      2) "paul"*      3) "melo"*      4) "james"*/// 增加好友的亲密度
zincrby user:kobe 15 james
​
// 再次根据“亲密度”给好友排序
zrevrange user:kobe 0 -1
​
/*** 输出:*      1) "james"*      2) "wade"*      3) "paul"*      2) "melo"*///类似的需求还出现在根据文章的阅读量或点赞量对文章列表排序

(2)排行榜

实效性

从排行榜的实效性上划分,主要分为:

  • 实时榜:基于当前一段时间内数据的实时更新,进行排行。例如:当前一小时内游戏热度实时榜,当前一小时内明星送花实时榜等

  • 历史榜:基于历史一段周期内的数据,进行排行。例如:日榜(今天看昨天的),周榜(上一周的),月榜(上个月的),年榜(上一年的)

业务数据类型

从需要排行的数据类型上划分,主要分为:

  • 单类型数据排行榜:是指需要排行的主体不需要区分类型,例如,所有用户积分排行,所有公贡献值排行,所有游戏热度排行等

  • 多类型(复合类型)数据排行榜:是指需要排行的主体在排行中要求有类型上的区分,例如:竞技类游戏热度排行、体育类游戏热度排行、MOBA类游戏操作性排行、角色/回合/卡牌三类游戏热度排行等

展示唯度

从榜单的最终展示唯度上划分,主要分为:

  • 单唯度:是指选择展示的排行榜就是基于一个唯度下的排行,例如前面提到的MOBA类游戏操作性排行榜,就仅展示所有MOBA类游戏按操作性的评分排行

  • 多唯度:是指选择展示的排行榜还有多种唯度供用户选择,仍然以前面的MOBA类游戏为例,唯度除了操作性,还有音效评分排行,难易度评分排行,画面评分排行等。

展示数据量

从需要展示的数据量上划分,主要分为:

  • topN数据:只要求展示topN条排行纪录,例如:最火MOBA游戏top20

  • 全量数据:要求展示所有数据的排行,例如:所有用户的积分排行

八.项目中哪些地方用到了Redis

数据采集字典表基础数据

最新数据采集值

物联网设备传送byte[]缓存

环境阈值

参考:https://yq.aliyun.com/articles/72666?t=t1

https://www.imooc.com/article/70762

Redis在项目中的地位及使用场景剖析相关推荐

  1. (五)Redis在项目中应用

    目录 1. redis实现分布式锁 2. 订单或任务缓存 3. Redis和DB数据一致性 4. 大并发Redis穿透直接访问DB 5. 接口限流器 参考: Redis在项目中的运用总结 1. red ...

  2. Redis在项目中的使用及性能测试(续)

    [前言] 在上篇博文<SCPPO:Redis在项目中的使用及性能测试>中小编为大家分享了在程序中引入Redis以及性能的提升,不过遗留了功能的完善以及性能在服务器上的测试,咱们就一鼓作气, ...

  3. Redis在项目中的使用及性能测试

    强烈推荐一个大神的人工智能的教程:http://www.captainbed.net/zhanghan [前言] 在上篇博文中为大家分享了<SCPPO:C#中Redis封装的类>,有了这个 ...

  4. 8.redis解决分布式session问题 、redis在项目中难点

    a.什么是session session是一种会话技术,我们知道http是无状态协议的,就是这次连接传输数据后,下次连接服务器是不知道这次的请求是谁的,因此我们要做一个标记,让服务器知道每次请求是哪个 ...

  5. java单例模式的应用场景_java项目中单列模式适用于什么场景?

    单例(Singleton)模式 也叫单态模式,是java的23种设计模式之一.网上很多介绍,我就言简意赅点了. 一.单例模式的应用场景 1.整个程序的运行中只允许有一个类的实例: 2.需要频繁实例化然 ...

  6. Redis在项目中合理使用经验总结

    背景 Redis 是一个开源的内存数据结构存储系统. 可以作为数据库.缓存和消息中间件使用. 支持多种类型的数据结构. Redis 内置了 复制(replication),LUA脚本(Lua scri ...

  7. Redis 在项目中合理使用经验总结

    背景 Redis 是一个开源的内存数据结构存储系统. 可以作为数据库.缓存和消息中间件使用. 支持多种类型的数据结构. Redis 内置了 复制(replication),LUA脚本(Lua scri ...

  8. 【精品】Redis在项目中的应用场景

    Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String 缓存 简单key-value存储 热 ...

  9. Redis在项目中的应用(点评)

     一.缓存更新策略 主动更新策略 先删除缓存时,由于更新数据库耗时较多,在此期间如有另一线程查询缓存/数据库并写入缓存,则当前线程更新数据库后会导致缓存和数据库数据不一致,而反之出现不一致的概率要小得 ...

最新文章

  1. python中pygame模块的Linux下安装过程
  2. Qt下的OpenGL 编程(1)Qt下的OpenGL编程必须步骤
  3. xBIM(eXtensible Building Information Modelling)可扩展的建筑信息模型
  4. 实例25:python
  5. 《Python Cookbook 3rd》笔记(5.16):增加或改变已打开文件的编码
  6. Linux下性能测量和调试诊断工具Systemtap
  7. 最便宜的双模5G手机来了!其它单模5G瞬间无光
  8. linux终端安装mingw编译器_C/C++编译器MinGW的安装与配置
  9. Python基础(函数)
  10. 80后的你现在有多少资产?
  11. jQuery1.11源码分析(8)-----jQuery调用Sizzle引擎的相关API
  12. 华为-----任正非
  13. cnn 一维时序数据_多角度理解CNN网络
  14. 计算机应用基础第四版答案周南岳,计算机应用基础周南岳答案.docx
  15. MoleBox PRO build 2.3.054,, Latest , Private Member Build Edition
  16. 实现HTML格式电子邮件群发
  17. python中的f的用法_python中f是什么
  18. html5 canvas 画板 demo,html5 canvas 简单画板实现代码
  19. MATLAB实现支持向量机SVM分类简介
  20. 基于SSM的概念可视化程序设计学习系统 毕业设计-附源码021009

热门文章

  1. IBM收购National Interest Security
  2. 基于tomcat5.5的数据库连接池环境设置(省的以后找系列)
  3. 一个 冒泡排序 和 选择排序 的简单c程序
  4. 写代码抽取代码的技巧
  5. 区块链入门与去中心化应用实战 之一 第2章 区块链技术的核心概念和原理
  6. PHP排雷之编码问题
  7. redis专题:redis集群的动态扩容缩容,水平扩展
  8. 选择排序、冒泡排序、异或运算
  9. SpringBoot整合AOP + 自定义注解实现简单的权限验证
  10. 重装linux服务器简易流程