为什么分布式一定要有Redis?( 二 )

  • 随着快递的增多 , 快递员也越来越多 , 小曲发现快递店里越来越挤 , 没办法雇佣新的快递员了 。
  • 快递员之间的协调很花时间 。
  •  
    综合上述缺点 , 小曲痛定思痛 , 提出了下面的经营方式 。
    经营方式二
     
    小曲只雇佣一个快递员 。然后呢 , 客户送来的快递 , 小曲按送达地点标注好 , 然后依次放在一个地方 。
    最后 , 那个快递员依次的去取快递 , 一次拿一个 , 然后开着车去送快递 , 送好了就回来拿下一个快递 。
    上述两种经营方式对比 , 是不是明显觉得第二种 , 效率更高 , 更好呢?
    在上述比喻中:
    • 每个快递员→每个线程
    • 每个快递→每个 Socket(I/O 流)
    • 快递的送达地点→Socket 的不同状态
    • 客户送快递请求→来自客户端的请求
    • 小曲的经营方式→服务端运行的代码
    • 一辆车→CPU 的核数
     
    于是我们有如下结论:
    • 经营方式一就是传统的并发模型 , 每个 I/O 流(快递)都有一个新的线程(快递员)管理 。
    • 经营方式二就是 I/O 多路复用 。只有单个线程(一个快递员) , 通过跟踪每个 I/O 流的状态(每个快递的送达地点) , 来管理多个 I/O 流 。
     
    下面类比到真实的 Redis 线程模型 , 如图所示:
     
    为什么分布式一定要有Redis?

    文章插图
     
     
    简单来说 , 就是我们的 redis-client 在操作的时候 , 会产生具有不同事件类型的 Socket 。
    在服务端 , 有一段 I/O 多路复用程序 , 将其置入队列之中 。然后 , 文件事件分派器 , 依次去队列中取 , 转发到不同的事件处理器中 。
    需要说明的是 , 这个 I/O 多路复用机制 , Redis 还提供了 select、epoll、evport、kqueue 等多路复用函数库 , 大家可以自行去了解 。
    Redis 的数据类型 , 以及每种数据类型的使用场景
     
    是不是觉得这个问题很基础?我也这么觉得 。然而根据面试经验发现 , 至少百分之八十的人答不上这个问题 。
    建议 , 在项目中用到后 , 再类比记忆 , 体会更深 , 不要硬记 。基本上 , 一个合格的程序员 , 五种类型都会用到 。
    String
     
    这个没啥好说的 , 最常规的 set/get 操作 , Value 可以是 String 也可以是数字 。一般做一些复杂的计数功能的缓存 。
    Hash
     
    这里 Value 存放的是结构化的对象 , 比较方便的就是操作其中的某个字段 。
    我在做单点登录的时候 , 就是用这种数据结构存储用户信息 , 以 CookieId 作为 Key , 设置 30 分钟为缓存过期时间 , 能很好的模拟出类似 Session 的效果 。
    List
     
    使用 List 的数据结构 , 可以做简单的消息队列的功能 。另外还有一个就是 , 可以利用 lrange 命令 , 做基于 Redis 的分页功能 , 性能极佳 , 用户体验好 。
    Set
     
    因为 Set 堆放的是一堆不重复值的集合 。所以可以做全局去重的功能 。为什么不用 JVM 自带的 Set 进行去重?
    因为我们的系统一般都是集群部署 , 使用 JVM 自带的 Set , 比较麻烦 , 难道为了一个做一个全局去重 , 再起一个公共服务 , 太麻烦了 。
    另外 , 就是利用交集、并集、差集等操作 , 可以计算共同喜好 , 全部的喜好 , 自己独有的喜好等功能 。
    Sorted Set
     
    Sorted Set多了一个权重参数 Score , 集合中的元素能够按 Score 进行排列 。
    可以做排行榜应用 , 取 TOP N 操作 。Sorted Set 可以用来做延时任务 。最后一个应用就是可以做范围查找 。
    Redis 的过期策略以及内存淘汰机制
     
    这个问题相当重要 , 到底 Redis 有没用到家 , 这个问题就可以看出来 。
    比如你 Redis 只能存 5G 数据 , 可是你写了 10G , 那会删 5G 的数据 。怎么删的 , 这个问题思考过么?


    推荐阅读