当前位置:首页 > 问答 > 正文

Redis用得不对地方,哪些业务场景其实挺难撑得住的

Redis是个好东西,速度快,用起来也简单,所以很多团队一遇到性能问题,第一个想到的就是用它,但俗话说得好,好东西用错了地方,反而会带来更大的麻烦,有些业务场景,如果硬要用Redis去扛,不仅达不到预期的效果,还可能把系统搞垮,这里就聊聊哪些情况是Redis比较吃力甚至撑不住的。

最典型的就是用它来处理大量的大数据集合操作,Redis虽然快,但它的数据是全部放在内存里的,内存有多贵,大家都知道,如果你有个业务,比如要存储用户长达一年的行为日志,每条日志都不大,但用户量一上来,总数据量可能达到几个TB甚至更多,这时候你要是想把这么多数据都塞进Redis,光硬件成本就是一笔巨大的开销,非常不划算,这种海量数据、低访问频率的场景,更适合用HBase、Cassandra这类分布式存储,或者干脆用传统的关系型数据库加索引,Redis应该用来存那些真正需要快速访问的热点数据,比如用户的会话信息、热门商品的缓存,而不是当作一个什么都能装的“万能仓库”。(来源:多位资深工程师在技术社区如知乎、CSDN上的经验分享)

第二个Redis容易撑不住的场景,是涉及复杂、耗时的数据计算,Redis提供了像Lua脚本这样的功能,允许你在服务器端执行一些逻辑,但有些人会误以为可以把复杂的业务计算都塞到Lua脚本里跑,觉得这样能减少网络往返,提升效率,这个想法是好的,但忽略了Redis一个关键特性:它是单线程的!Redis的所有操作,包括你那个复杂的Lua脚本,都是在这个主线程上排队执行的,如果你的脚本逻辑很复杂,需要遍历很大的集合,或者进行了大量的计算,那么这个脚本就会长时间霸占着这个唯一的线程,在这期间,Redis就不能响应其他任何客户端的请求,整个服务就相当于“卡住”了,这会导致所有依赖这个Redis的服务接口超时,进而可能引起整个系统的雪崩,复杂的分析和计算任务,应该交给专门的应用服务器或者大数据计算框架(如Spark、Flink)去做,Redis只负责提供原始数据或存储结果。(来源:Redis官方文档关于Lua脚本和单线程模型的警告,以及《Redis设计与实现》一书中的相关章节)

第三个问题是用Redis做消息队列时,盲目追求持久化和可靠性,Redis的List结构经常被拿来当简单的消息队列用,用LPUSH和RPOP命令实现生产者和消费者,对于丢失少量消息也无所谓的场景,比如更新排行榜、发个通知,这确实简单高效,但有些业务场景对消息的可靠性要求极高,比如订单支付、资金结算,绝对不能丢消息,这时候,如果用Redis的简单队列,就会面临风险:如果Redis突然宕机,内存里还没来得及持久化到硬盘的消息就全丢了,虽然Redis有AOF和RDS两种持久化机制,但它们都是为了数据恢复设计的,并不是为消息队列的可靠性保证而生的,配置不当的话,仍然可能丢数据,真正的消息队列中间件,比如RabbitMQ、Kafka,它们的设计核心就是高可靠、不丢消息,支持消息确认、持久化、重试等一整套机制,用Redis来顶替它们处理金融级业务,无异于走钢丝。(来源:技术博客中对Redis与专业消息队列的对比分析,如阿里云开发者社区等)

第四,对于需要复杂查询的业务,Redis会显得力不从心,Redis的查询模式非常单一,基本上就是通过Key来获取Value,虽然它提供了Set、ZSet(有序集合)、Hash这些数据结构,但查询方式依然很受限,你想查询“所有年龄大于30岁且城市在北京的用户”,这种在多列上进行筛选的SQL查询,在关系数据库里一句SQL就能搞定,但用Redis来实现会非常别扭和低效,你可能需要维护很多个不同的索引集合(比如一个Set存所有北京用户,一个ZSet存用户年龄),然后取交集、并集,这个过程不仅开发复杂,而且非常消耗CPU资源,这种需要多维度、ad-hoc(即席)查询的场景,关系型数据库或者专门的搜索引擎(如Elasticsearch)才是正确的选择。(来源:数据库领域常见的Redis与SQL/NoSQL数据库适用场景对比文章)

还有一个容易被忽略的点:Redis在集群模式下的局限性,当数据量大到一台机器装不下时,就需要用Redis Cluster或者Codis这类方案进行分片,分片之后,一些原本在单机上很好用的操作就会出问题,最典型的就是涉及多个Key的操作,比如求两个Set的交集(SINTER命令),如果这两个Set的Key恰好被分配到了不同的Redis节点上,这个命令就无法执行,虽然有些客户端工具能在本地模拟实现,但性能和可靠性都大打折扣,还有,事务(MULTI/EXEC)在集群环境下也只能在单个Key上生效,无法保证跨多个节点的数据一致性,如果你的业务逻辑严重依赖跨Key的复杂事务或聚合操作,那么Redis集群可能会成为一个架构上的陷阱。(来源:Redis Cluster官方规范以及分布式系统相关的技术演讲)

Redis是一把锋利的“瑞士军刀”,但它不是万能的,把它用在缓存、会话存储、排行榜、简单的消息队列等核心是“快”的场景,它能发挥巨大价值,但如果业务涉及海量数据存储、复杂计算、高可靠消息、多维度查询或跨分片事务,强行使用Redis往往会事倍功半,甚至给系统带来稳定性和成本上的风险,选择合适的工具做合适的事,才是架构设计的精髓。

Redis用得不对地方,哪些业务场景其实挺难撑得住的