Redis 经典问答、经典案例分析实现、应用场景总结

1. Redis 经典问题

1.1 Redis 持久化方式有什么区别?

  • RDB 方式和 AOF 方式
    • RDB 方式的持久化是通过快照完成的,生成一份副本,并存储到硬盘上
    • AOF 是将 Redis 执行的每一条写命令追加到硬盘文件上。
  • RDB 的优点
    • RDB 是一个非常紧凑的文件,它保存了某个时间点上的数据集,非常适用于数据的备份
    • RDB 是一个紧凑的单一文件,非常适合于灾难恢复
    • RDB 在保存 RDB 文件时父进程唯一需要做的就是复制出一个子进程,接下来的所有的工作全部由子进程来做,父进程不需要做其他 IO 操作,所以 RDB 持久化方式可以最大化 Redis 的性能
    • 与 AOF 相比,在恢复大数据集的时候,RDB 方式会更快一些
  • RDB 的缺点
    • 如果希望在 Redis 意外停止工作的情况下丢失的数据最少的话,那么 RDB 不适合,Redis 要完整的保存整合数据集是一个比较繁重的工作。
    • RDB 需要经常复制子进程来保存数据集在硬盘上,当数据集比较大的时候,复制的过程是非常耗时的,可能会导致 Redis 在一些毫秒级内不能响应客户端的请求。
  • AOF 的优点
    • 使用 AOF 可以使 Redis 更加耐久:可以使用不同的同步策略:无同步,每秒同步,每次写的时候同步
    • AOF 文件是一个只进行追加的日志文件,所以不需要写入 seek
    • Redis 可以在 AOF 文件体积变得过大时,自动地在后台对AOF 进行重写
    • AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析也很轻松。 导出 AOF 文件也非常简单
  • AOF 的缺点
    • 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积
    • 根据所使用的同步策略,AOF 的速度可能会慢于 RDB。

1.2 Redis 过期时间如何实现

  • 惰性删除和定期删除
    • 惰性删除策略不会在键过期的时候立即删除,而是当外部指定获取这个键的时候才会主动删除。处理的过程为:接收 get() 执行、判断是否过期、执行删除操作、返回为空。
    • 定期删除是设置一个时间间隔,每个时间段都会检测是否有键过期,如果有,就执行删除操作。

1.3 Memcached 与 Redis 的区别都有哪些

  • Redis 有丰富的数据类型。Memcached 所有的值都是简单的字符串。Redis 支持更多丰富的数据类型:字符串、哈希、列表、集合、有序集合
  • 内存管理机制。在 Redis 中并不是所有的数据都是存储在内存中的,当物理内存用完时,Redis 可以将一些很久没有用到的值交换到磁盘。Redis 只会缓存所有的 key 的信息,如果 Redis 发现内存使用的量超过了某一个阈值,将触发 swap(交换)的操作,计算出哪些 key 对应的值要swap 到磁盘,然后再把这些键对应的值持久化到磁盘中,同时在内存中清除。这种特性使得 Redis 可以保持其超过机器本身内存大小的数据
  • 过期时间的处理方式不一样。Redis 是用惰性删除和定期删除,而memcached 使用的是惰性删除。
  • Redis 可以持久化数据。虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供了两种持久化策略:RDB 快照和 AOF 日志。而 Memcached 是不支持数据持久化操作的
  • Redis 支持事务。而 Memcached 不支持
  • 集群管理的不同。
    • Memcached 本身并不支持分布式,因此只能在客户端通过像“一致性hash”这样的分布式算法来实现 Memcached 的分布式存储。当客户端向 Memcached 集群发送数据之前,首先会通过内置的分布式算法计算出该条数据的目标节点,然后将数据发布到该节点上存储。当客户端查询数据时,同样要计算出数据所在的节点,然后向该节点发送查询请求获取数据。相较于 Memcached 只能采用客户端实现分布式存储,Redis 更偏向于服务端构建分布式存储。
    • 新版本的 Redis 支持分布式存储功能。Redis cluster 是一个实现了分布式且允许单点故障的 Redis 高级版本。它没有中心节点,具有延伸性、可伸缩功能。

1.4 MySQL 里有2000万数据,如何查询热点数据

  • 服务器的内存是有限的,如果大量使用缓存键、且过期时间设置的过长,就会导致 Redis 占满内存。为此可以设置 Redis 可以使用的最大内存并让 Redis 按照一定的规则淘汰不需要的缓存的键。Redis提供了 6 种数据淘汰策略
  1. 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
  2. 从已设置的过期时间的数据集中挑选将要过期的数据淘汰
  3. 从已设置的过期时间的数据集中任意选择数据淘汰
  4. 从数据集中挑选最近最少使用的数据淘汰
  5. 从数据集中任意选择数据淘汰
  6. 禁止淘汰数据
  • 具体设置方式为,修改配置文件 maxmemory 参数,限制 Redis 最大的可用内存大小,当超出了这个限制时,Redis 会依据 maxmemory-policy 参数指定的策略来删除不需要的键,直到 Redis 占用的内存小于指定的内存。
  • 我们可以利用 Redis 的这个特性在系统的架构中增加一层 Redis 的缓存层。当访问 MYSQL 的数据时,先去缓存中查找,如果不存在就查出 MySQL 中的数据进行缓存。我们配置 Redis 最大内存策略为“从数据集中挑选最近最少使用的数据淘汰”,这样保存到 Redis 中的数据就是热点数据。

2. Redis 经典案例分析实现

2.1 基于 Redis 实现分布式锁

  • 业务背景:随着大型网站的各种高并发访问,海量数据处理等场景越来越多,如何实现网站的高可用、易伸缩、可扩展、安全的目标就显得越来越重要。为了解决这一系列的问题,大型网站的架构也在不断的发展。提高大型网站的高可用架构,不得不提的就是分布式。

    • 分布式就是一个业务分拆成多个子业务、一个大系统分拆成各个子服务,部署在不同的服务器上。
    • 目前几乎很多大型网站及应用都是分布式部署的,在很多场景中我们为了保证数据的最终一致性,需要很多的技术方案来支持,分布式锁是控制分布式系统之间同步访问共享资源的一种方式。
    • 在分布式系统中常常需要协调它们的动作。如果不同的系统或者同一系统的不同主机之间共享了一个或者一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性。在这种情况下便需要使用到分布式锁。
    • 在很互联网产品应用中,有一些场景需要加锁处理,比如秒杀、全局递增 id 等等。
  • 存在的挑战

    • 分布式锁:要保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行
    • 避免死锁
    • 有高可用的获取锁和释放锁的功能
    • 获取锁和释放锁的性能要好。
  • 解决思路

    • SETNXGETSET 实现分布式锁机制
    • 用过期时间来处理死锁
  • 实例:。。。

2.2 利用 Redis 实现 亿级别用户登录统计

  • 业务背景

    • 现在有一个业务需求,需要从一批很大的用户活跃数据(2亿+)中判断用户是否为活跃用户。由于此数据是基于用户的各种行为日志筛选才能得到,数据部门不能提供实时接口,只能提供包含用户及是否活跃的指定格式的文本由业务方使用。
    • 一个拥有上亿用户的商城系统或游戏系统,统计连续一周登录的用户,赠送礼品券或游戏币,实时查询数据库对数据库有一定的压力,且响应缓慢。
  • 存在的挑战

    • 海量数据如何尽可能用小的空间存储
    • 快速获取指定的数据
    • 快速写入到目标存储
    • 数据统计计算方便
  • 解决思路

    • 使用 Redis 的有序集合,但是用户量过大的时候有序集合会占用很大的内存空间
    • Redis 的位操作

2.3 Redis 经典案例队列的实现

  • 业务背景

    • 在一个商城系统中,用户购买流程如下:
    • 下单 ——> 支付 ——> 申请快递单号 ——> 通知仓库打包发货 ——> 发送短信邮件、增加积分、订阅快递信息
    • 如果用户等待这一系列流程走完,返回购买成功。响应速度慢,用户体验差,系统耦合度过高。
    • 为了改善这种体验,我们需要用到队列
  • 存在的挑战

    • 提高系统响应速度
    • 异步处理
    • 应用解耦
    • 流量削峰
  • 解决思路

    • Redis 的列表
    • Rpush + Blpop 或 Lpush + Brpop

2.4 Redis 经典案例秒杀的实现

  • 业务背景:在商城系统中,经常搞一些显示促销活动,比如秒杀,所谓秒杀,从业务角度看,是短时间内多个用户争抢商品。将业务抽象,技术角度看,秒杀就是多个线程对资源进行操作。所以实现秒杀,就必须控制线程对资源的争抢,既要保证高效并发,也要保证库存不能超卖。

  • 存在的挑战

    • 避免库存超卖
    • 客户端响应要快
    • 系统稳定性
    • 避免作弊、比如僵尸号
  • 解决思路

    • Redis 字符串的 get、decrby

3. Redis 应用场景总结

3.1 String 应用场景

  • 原子计数器。统计文章访问量。每个单一 Redis 命令都是原子操作,不会产生并发情况导致计算数据不准确。所以使用 incr 命令增加访问量,返回值为增加后的数值。
  • 分布式锁。运用 setnx 实现分布式锁,用 expire 防止死锁。
  • 单点登录。在多个应用系统中,用户只需要登录一次,就可以访问所有相互信任的应用系统。如果要实现一次登录和一次退出,可以利用 SESSION 共享,SESSION 存储到 Redis 中,多个服务都可以去 Redis 中验证用户的 SESSION。而且存取速度快,数据不容易丢失,用户多的情况下容易支持集群,能够统计在线用户。
  • 数据缓存。Redis 是一个开源的、高性能的、基于键值对的缓存与存储系统。它可以用作数据库缓存消息中间件。做数据缓存的功能、缓存整个静态页面或者是缓存 JSON 数据非常合适。
  • 秒杀场景中的库存管理。在 Redis 中管理库存也是基于每个单一的 Redis 命令都是原子操作的属性,来避免并发情况导致库存计算错误。
  • 活跃度以及登录次数的统计。可以用 Redis 字符串的位运算来统计亿级别用户的活跃度和登录次数。

3.2 Hash 应用场景

  • 键值对信息,如用户信息、文章信息的数据。Redis 搭建新闻系统,就是讲文章的字段:比如标题、内容、作者等信息存储到 Redis 中。

3.3 List 应用场景

  • 访问频率限制。可以用列表实现统计一个用户在一定时间内的访问记录统计。有了这个记录就就可以实现访问频率的限制。
  • 队列。队列的属性就是先进先出。因为列表是有序的,可以使用 lpushrpop 来实现队列功能。
  • 优先级队列lpop 实现。
  • 分页。利用列表可以使用 lrange 命令获取一定范围的值,通过 llen 来获取总数,且列表中的元素是有序的,可以将 id 存为列表,实现分页功能。
  • 最新排行。利用列表的有序性,获取最新插入列表的数据

3.4 Set 应用场景

  • 共同好友。通过多个好友集合求交集,可以计算出共同的好友。大于某个临界值可以推荐给自己的好友。
  • 二度好友。就是好友的好友。通过所有好友的好友求并集,计算出自己的二度好友。
  • 标签。通过集合求交集和并集。
  • 统计访问网站的独立 IP。通过集合的互异性,就是集合中所有的元素都是不重复的,来统计网站独立 IP
  • 数据排重。比如抢红包,抢过红包的人就不能再抢。利用了集合的互异性。

3.5 Zset 应用场景

  • 最新排行。有序集合就是为集合的每个元素都关联了一个分数。不仅可以完成集合类型支持的操作,还可以获得指定分数范围内的元素。最新排行可以利用时间来做分数。
  • 最热排行。可以用访问量来作为分数。
  • 用户得分排行榜。有序集合可以通过分数来获取元素的时候,加上不同的权重,这样就可以根据不同的权重乘以分数算出不同等级用户的得分排行榜。
  • 网站最近的访问用户,活跃用户。可以把所有用户的 id 作为键值,每天的登录次数作为分数,记录到 KEY 为当天日期的有序集合里,通过计算当天有序集合的元素个数,来统计当天的活跃用户,对有序集合求交集来统计网站连续几天登录的访问用户。

你可能感兴趣的:(Redis,缓存技术)