关于redis 的一些好文章 - (sunznx) 振翅飞翔
23 October 2019

汇总下,我看过关于 redis 的好文章,排名有分先后

  • 选redis还是memcache,源码怎么说?

    这篇文章对 “持久化” 和 “高可用” 的功能说的比较明白

    持久化

    mc 无法满足持久化的需求,只得选择 redis。但是,这里要提醒的是,真的使用对了 redis 的持久化功能么?

    千万不要把 redis 当作数据库用:
    (1)redis 的定期快照不能保证数据不丢失
    (2)redis 的 AOF 会降低效率,并且不能支持太大的数据量
    不要期望 redis 做固化存储会比 mysql 做得好,不同的工具做各自擅长的事情,把 redis 当作数据库用,这样的设计八成是错误的。

    缓存场景,开启固化功能,有什么利弊?
    如果只是缓存场景,数据存放在数据库,缓存在 redis,此时如果开启固化功能:
    优点是,redis 挂了再重启,内存里能够快速恢复热数据,不会瞬时将压力压到数据库上,没有一个 cache 预热的过程。
    缺点是,在 redis 挂了的过程中,如果数据库中有数据的修改,可能导致 redis 重启后,数据库与 redis 的数据不一致。(另外,固化肯定有性能开销)
    因此,只读场景,或者允许一些不一致的业务场景,可以尝试开启 redis 的固化功能。

    高可用

    redis 天然支持集群功能,可以实现主动复制,读写分离。
    redis 官方也提供了 sentinel 集群管理工具,能够实现主从服务监控,故障自动转移,这一切,对于客户端都是透明的,无需程序改动,也无需人工介入。
    而 memcache,要想要实现高可用,需要进行二次开发,例如客户端的双读双写,或者服务端的集群同步。

    但是,这里要提醒的是,大部分业务场景,缓存真的需要高可用么?
    (1)缓存场景,很多时候,是允许 cache miss
    (2)缓存挂了,很多时候可以通过 DB 读取数据
    所以,需要认真剖析业务场景,高可用,是否真的是对缓存的主要需求?
    画外音:即时通讯业务中,用户的在线状态,就有高可用需求。

    内存分配

    memcache 使用预分配内存池的方式管理内存,能够省去内存分配时间。
    redis 则是临时申请空间,可能导致碎片。
    从这一点上,mc 会更快一些。

    虚拟内存使用

    memcache 把所有的数据存储在物理内存里。
    redis 有自己的 VM 机制,理论上能够存储比物理内存更多的数据,当数据超量时,会引发 swap,把冷数据刷到磁盘上。
    从这一点上,数据量大时,mc 会更快一些。

  • 10个常见的Redis面试"刁难"问题

    使用过 Redis 做异步队列么,你是怎么用的?

    一般使用 list 结构作为队列,rpush 生产消息,lpop 消费消息。当 lpop 没有消息的时候,要适当 sleep 一会再重试。
    如果对方追问可不可以不用 sleep 呢?list 还有个指令叫 blpop,在没有消息的时候,它会阻塞住直到消息到来。
    如果对方追问能不能生产一次消费多次呢?使用 pub/sub 主题订阅者模式,可以实现 1:N 的消息队列。
    如果对方追问 pub/sub 有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如 rabbitmq 等。
    如果对方追问 redis 如何实现延时队列?我估计现在你很想把面试官一棒打死如果你手上有一根棒球棍的话,怎么问的这么详细。但是你很克制,然后神态自若的回答道:使用 sortedset,拿时间戳作为 score,消息内容作为 key 调用 zadd 来生产消息,消费者用 zrangebyscore 指令获取 N 秒之前的数据轮询进行处理。
    到这里,面试官暗地里已经对你竖起了大拇指。但是他不知道的是此刻你却竖起了中指,在椅子背后。

    补充:针对 redis list/pubsub 实现消息队列,生产的消息会丢失的解决方案

    1. 使用 redis 5 的 stream
    2. 曲线救国方案:使用多一个备用列表,消息给消费者之后,再 append 进备用列表。消费者的消息丢了之后,可以从备用列表里面拉取

    如果有大量的 key 需要设置同一时间过期,一般需要注意什么?

    如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,redis 可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。

    Redis 的同步机制了解么?

    Redis 可以使用主从同步,从从同步。第一次同步时,主节点做一次 bgsave,并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制节点,复制节点接受完成后将 rdb 镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

    是否使用过 Redis 集群,集群的原理是什么?

    Redis Sentinal 着眼于高可用,在 master 宕机时会自动将 slave 提升为 master,继续提供服务。
    Redis Cluster 着眼于扩展性,在单个 redis 内存不足时,使用 Cluster 进行分片存储。

  • Redis为什么是单线程

    Redis 为什么是单线程的?
    因为 CPU 不是 Redis 的瓶颈。Redis 的瓶颈最有可能是机器内存或者网络带宽。

    如果万一 CPU 成为你的 Redis 瓶颈了,或者,你就是不想让服务器其他核闲置,那怎么办?
    那也很简单,你多起几个 Redis 进程就好了。Redis 是 key-value 数据库,又不是关系数据库,数据之间没有约束。只要客户端分清哪些 key 放在哪个 Redis 进程上就可以了。redis-cluster 可以帮你做的更好。

  • 节约内存:Instagram 的 Redis 实践
    长话短说,在 redis 中,如果 key 的数量太多的话,实际上也会消耗不少内存,可以使用 hash 来合并多个 key
  • 使用redis和mysql访问同样的数据的性能测试结果令人感到困惑!

    按照常理来说,从内存中取数据比从磁盘中取数据快,今天使用 redis 和 mysql 分别对同样的数据进行访问,测试结果令人大跌眼镜,两者获取数据的时间相差无几,这样的结果让人实在是困惑,为何 redis 访问数据的时间与 mysql 差不多?如果是这样,使用 redis 还有什么优势?根本不能提高访问数据的性能?望各位解答一下,为何会出现这样的结果?

    下面是一些比较经典的回复:

    • 你和 F1 赛车站在一条起跑线上比赛,发令枪响后同时启动,若干毫秒后,你和 F1 赛车的距离几乎没什么区别,难道你能说你和赛车的速度差不多么。
    • 常识问题从内存读数据肯定比从磁盘度快,但是,如果是磁盘顺序读,其实也就快个几十微秒,如果说随机读,那就会快几十毫秒,甚至更多。MySQL 本身也有自己的 Cache 呀,从 Mysq 本身的 Cache 读和从 redis、memcache 读没有本质上的区别
    • Redis 的大部分消耗都在网络通讯和 IPC 中,这意味着和关系数据库比较读取性能毫无意义,因为大部分的 IO 瓶颈都受限于网络。另外 Redis 是单线程服务,直接用来和多线程的数据库对比也是不公平的。

    然后是我的观点:
    redis 一般是当成 mysql 的 cache 来使用。上面得出的测试结果,应该是 mysql 的数据量比较小,如果 mysql 有几千万条数据,那么结果就很显然了。当然了,redis 存几千万条数据也不合适。我的观点是 redis 存的是 mysql 的子集的时候(例如排名前 100 的数据),这时候 redis 的作用就很显然了。

  • redis 锁相关
    解锁 Redis 锁的正确姿势
    Redis 分布式锁进化史(解读 + 缺陷分析)
  • 阿里云Redis的开发规范,值得借鉴!
  • BAT 等 IT 大厂们都在用什么 Redis 集群方案
  • Codis作者黄东旭细说分布式Redis架构设计和踩过的那些坑们