龙空技术网

mysql 与 redis 的选型问题实践

实战Java 124

前言:

当前看官们对“mysql替代redis”可能比较关怀,大家都想要剖析一些“mysql替代redis”的相关内容。那么小编同时在网摘上收集了一些有关“mysql替代redis””的相关文章,希望你们能喜欢,各位老铁们一起来学习一下吧!

背景

当前系统当前使用 mysql+redis 的技术架构,现需要对该系统进行重构工作,其中就需要对数据存储技术进行选型。

业务场景如下:

该系统为油站价格优惠系统,涉及众多油站(1w+)、商品(92/95/柴油/天然气等)、渠道(端内各渠道/各大 C 共 1k+)维度,涉及价格数量共 1 亿(1wx10x1k)。优惠策略除各维度价格之外,还存在城市、全国维度等非“单点”策略。优惠策略存在周期、人群等复杂筛选条件。

技术细节如下:

运营在后台配置优惠策略,数据保存在 mysql 数据库;C 端用户需要获取某一门店商品价格,需要根据条件查询 mysql 数据库,并对查询结果进行匹配过滤;后因性能问题引入缓存,对各维度查询结果进行缓存;后又因缓存穿透、性能问题,演变成:C 端不读区数据库只读区缓存,运营配置完成后进行一轮异步刷缓存。

选型需求如下:

以稳定性为主要目标,将系统拆分为配置域与执行域:配置域处理运营配置、数据刷新等复杂不可控的业务;策略加工后输送到运行域(即 C 端),运行域仅读取加工完的数据,进行简单的计算处理;现在需要找到一个合适的存储载体来存在这些加工好后的运营策略。系统当前运行状态下,对应的载体应该是 redis,但是作为数据存储载体,其是否合适需要进一步讨论。分析当前使用场景的要求查询场景:查询门店 x 商品 x 渠道维度对应的策略数据量:门店 x 商品 x 渠道,一共有 1 亿个渠道qps:当前访问峰值需要支持 1wqpsredis 作为存储载体

首先,redis 作为存储载体,是最“平滑”的选择,因为系统的现状,当前位置用的就是 redis。

但是,随着系统进行拆分,以及任务加工逻辑的复杂,继续使用 redis 会面临以下问题:

在执行域系统,redis 将成为唯一数据存储载体,这与 redis 本身作为缓存的定位有些不符;系统中的数据存储载体正常应该是基于磁盘的数据库,而非基于内存的缓存,虽然 redis 也支持持久化;

另外,redis 的数据查询能力较弱,无法支持 sql 查询,事务支持不完善。因为在当前场景无此要求,所以可以忽略。

当然,使用 redis 也有其优越性:

key-value 的结构天然适合当前场景的“定点”查询;redis 基于内存,能够支持高速访问;但同时也让 redis 的成本较高(虽然在企业使用上没有这方面考量);可以水平扩展,所以容易支持大数据量,高 qps。

总结:

从硬性要求考虑,redis 可以满足;但从功能定位上,把 redis 作为一个数据存储的载体,不怎么合适mysql 作为存储载体

另外一个方案就是使用回 mysql。

一般来说,从 mysql 转到 redis 都是因为性能问题,对热点 key 进行缓存,以提升访问速度,同时降低数据库的磁盘压力。

而系统当前引入 redis 的初衷,并非是为了热点数据的性能考量,而是因为某些“不得已”的性能瓶颈。所以在 redis 中缓存的并非只是热点数据,而是全盘的 key-value。

关于“不得已”的性能瓶颈:

前面的业务介绍有提到,除了门店-商品-渠道维度,还有类似“城市”、“全国”等全局维度;系统采取的方案是先查询当前维度的策略,然后再查一次城市维度的策略,最后合并到一起;随着城市维度的策略增多,数据库的响应时间出现问题,于是就因为“性能”问题引入了 redis。

上面的“优化”手段,其实并没有解决实质问题,只是将 mysql 中的“大数据量”问题换了一种形式存在:redis 中的大 key 问题。

在这之后,我们也掉到了这个坑里面;因为运营配置了较多的城市维度策略,引发了 redis 大 key(1.8M)问题,带来了一个线上故障。这也是这次重构工作的重要背景。

补充一句,在缓存出了问题之后,我们其实还可以将问题再次转移,给系统“续命”:将缓存中的 key 在应用本地再缓存一次。但这样做只会跟上一次“优化”的结果一样,给系统再一次埋下定时炸弹。

回到存储方案选型上来,通过历史我们可以得知:这个系统其实并不一定需要缓存。从线上的监控来看,mysql 的响应速度不比 redis 差太多。

那么,mysql 是否可以在当前场景作为存储方案的产品呢?

优点就不说了,直接看最为关键的两个问题:

响应速度:公司内部使用了 dbproxy 优化,从监控结果上看,性能跟 redis 所差不多;qps:需要添加备库以支撑 qps,当前公司可申请的最大规格无法满足 qps 要求,需要 dba 操作;数据量:需要进行分库分表,开发/维护成本较高。

总结:

从硬性要求考虑,mysql 可以满足;但分库分表开发维护成本较高redis + mysql

先不管是否可能,顺着前面的方案,采取 redis+mysql 方案会怎么样?

首先,redis 的“定位”问题解决,因为有了 mysql 来作为数据存储载体;然后,因为 redis 的缓存,qps 的问题可能会有一些缓解,但不一定能打包票,还要考虑命中率及缓存可用性的问题;最后 mysql 的大数据量无法解决,还是需要分库分表。一个 Redis 与 MySQL 之间的方案

前面我们说 redis 最大的问题是产品定位问题。那么,redis 为什么不适合作为存储载体?或者说,redis 为什么不能作为数据库替代 mysql?

我觉得核心问题是持久化能力。

redis 虽有 rdb、aof 两种持久化方式,但其本质是仍一个内存数据库,持久化只是用于辅助内存的读写,宕机仍存在丢失风险;aof 持久化虽然可以做到跟内存同步,但也是以牺牲性能作为代价的。

所以我们要找的应该是可持久化的、方便水平扩展的数据库产品。

刚好内部自研的 fusion 可以满足这个要求:

其定位介于 Redis 与 MySQL 之间,是一款基于 rocksdb 的主存储数据库,又实现了 redis 协议;部署在 ssd 之上,上层自带 cache 缓存;可支持水平扩展;内部有团队支持。

总结

数据结构:门店 x 商品 x 渠道

mysql:b+树索引组合查询可以支持,另外支持 sql 丰富的查询统计

redis:k-v 结构可以支持

qps:1wqps

mysql:需要添加备库以支撑 qps,当前公司可申请的最大规格无法满足 qps 要求,需要 dba 操作。redis:可以水平扩展

数据量

mysql:需要进行分库分表,开发/维护成本较高

redis:可以水平扩展

rt

mysql:公司内部使用了 dbproxy 优化,从监控结果上看,性能跟 redis 所差不多

redis:基于内存,快速

定位

mysql:基于磁盘,适合数据存储

redis:基于内存(有持久化做辅助),适合做缓存

结论

因为功能定位问题,不用 redis;

使用类似 mysql 的基于磁盘的数据产品,但需要解决 mysql 的两个问题;

使用 fusion,产品定位介于 mysql、redis 之间,是数据存储载体,又可以支持大数据量水平扩展、支持高 qps。

原文链接;

标签: #mysql替代redis