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

用Redis简单搭个系统,帮忙快速读MySQL数据,不用太复杂也能快点响应

这个想法的核心很简单,MySQL数据库就像一个大仓库,里面的东西放得井井有条,但是每次要拿东西(查询数据),都得进仓库里翻找一下,如果仓库很大,或者同时有很多人要拿东西,速度就会慢下来,而Redis就像一个放在仓库门口的超快临时货架,我们把仓库里最常被拿取的那些热门货物,提前摆在这个货架上,下次有人要这些热门货物,直接从门口货架拿,速度就快多了,根本不用进大仓库。

这个“临时货架”就是Redis,它是一种内存数据库,意思是所有数据都放在服务器的内存里,内存的读写速度比硬盘(MySQL数据通常存储在硬盘上)快几个数量级,所以响应速度能获得巨大提升。

我们来看看怎么搭这个简单的系统,整个过程可以分三步走:写数据、读数据、更新数据。

第一步:系统写入新数据时,如何操作?

当你的应用程序需要往数据库里存入新数据时,比如用户发布了一条新微博,或者新增了一个商品,这个阶段,最简单的做法是“先写数据库,再让缓存失效”,具体流程是这样的:

  1. 应用程序首先把新数据写入MySQL数据库,这是主流程,必须保证数据最终存入了永久仓库。
  2. 写入MySQL成功后,应用程序顺便发一个指令给Redis,告诉它:“喂,如果缓存里有某个相关的旧数据,把它删掉。”(注意:这里不是直接更新缓存,而是删除缓存) 引用来源:这是一种常见的缓存策略,常被称为“Cache-Aside Pattern”中的一种方式,核心思想是让数据的读取方在缓存失效时自己去更新缓存。

为什么这么做呢?因为如果新数据写入后,我们马上去更新Redis里的缓存,可能会遇到并发问题,比如两个请求同时来更新,可能导致缓存里的数据不是最新的,直接删掉缓存更简单、更安全,下次有人需要读这个数据时,自然会从MySQL里取出最新的数据并重新塞回Redis里,这样保证了数据的一致性,虽然可能有一瞬间的数据不一致(即从删除缓存到下次读取之间,如果有人读会读到旧数据并填回缓存),但对于大多数不需要强一致性的场景来说,是可以接受的。

第二步:应用程序读取数据时,如何操作?

这是发挥Redis作用的关键环节,当用户要查看某条数据时,比如查看刚才那条微博的详情,应用程序的处理逻辑应该是:

  1. 应用程序去查一下Redis缓存,它会用一個唯一的键(Key)来查找,weibo:123(123是微博的ID)。
  2. 如果运气好,在Redis里找到了这个数据(这种情况叫做“缓存命中”),太好了!直接把这个数据返回给用户,整个过程完全不需要打扰MySQL,速度极快。
  3. 如果Redis里没有找到(这种情况叫做“缓存未命中”),那就没办法了,只能按老路子来,应用程序转身去查询MySQL数据库。
  4. 从MySQL里拿到数据后,做两件事:把数据返回给用户;非常重要的是,把这个数据也存一份到Redis里,并且设置一个过期时间,比如10分钟或者1小时,这样,下一个用户再来请求同样的数据时,就能直接从Redis里快速获取了。

这个“设置过期时间”非常关键,它相当于给临时货架上的货物贴了个保质期,过了这个时间,货物自动下架(数据自动从Redis删除),这样做的目的是防止数据永远停留在缓存里,如果源头数据在MySQL里已经更新了,而缓存一直不失效,用户就会一直读到旧数据,设置一个合理的过期时间,是一种简单的保证数据最终一致性的方法。

第三步:当MySQL里的数据被更新了怎么办?

如果数据不是新增,而是修改,比如用户修改了微博内容,或者管理员调整了商品价格,处理方式和新增数据时很像,遵循“先更新数据库,再使缓存失效”的原则:

  1. 应用程序先去更新MySQL中的记录。
  2. 更新成功后,发送指令删除Redis中对应的缓存数据。

这样,下一次有请求来读取这个数据时,会发现缓存里没有(缓存未命中),于是就会去MySQL里取出最新的数据,并重新加载到Redis中,后续的读取请求就又可以从缓存中快速获取了。

一些简单的实践建议

  1. 缓存什么数据? 一开始,不要想着把所有数据都缓存起来,应该优先缓存那些“读多写少”的数据,比如新闻文章、商品分类、热门商品信息、用户的基本信息等,这些数据不经常变动,但被访问的频率很高,缓存它们性价比最高。
  2. 键(Key)的设计: 给缓存数据起名字(Key)要有点规律,user:1001 表示ID为1001的用户,product:category:5 表示分类ID为5的商品列表,这样自己管理起来也清晰。
  3. 内存管理: Redis是内存数据库,服务器的内存是有限的,你需要关注Redis的内存使用情况,除了给Key设置过期时间让其自动淘汰外,还可以配置Redis的内存淘汰策略,当内存不足时,让Redis自动淘汰掉一些最近最少使用的(LRU)数据,或者即将过期的数据,这也是保证服务稳定的重要手段。
  4. 不是万能的: 用了Redis不代表所有查询都会变快,它主要解决的是“频繁读取相同数据”的性能瓶颈,对于那些复杂的、每次都需要扫描大量表或进行复杂计算的查询,或者本身访问频率就很低的数据,缓存的意义不大。

用Redis给MySQL加速的这个简单系统,其核心流程就是:读的时候,先看缓存,缓存没有就读数据库并回填缓存;写的时候,先写数据库,然后删掉对应的缓存,通过这种简单直接的方式,就能用很小的代价,显著提升系统的读取响应速度,非常适合作为性能优化的第一步。

用Redis简单搭个系统,帮忙快速读MySQL数据,不用太复杂也能快点响应