redis 高并发缓存问题及解决

本贴最后更新于 2015 天前,其中的信息可能已经时移世易

如果我们项目中用到 redis,那么一定会存在缓存与数据库双写的问题,今天就讲讲双写可能存在的问题和解决思路。

一般的做法是
imagepng
这样就出现缓存与数据库双写不一致了。那么如何解决呢?
其实很简单,只要把先后顺序换一下就好了,先删除缓存,再去修改数据库。

这里就引出了一个概念:cache aside pattern
(1)读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应;
(2)更新的时候,先删除缓存,然后再更新数据库;

这个方法在并发不大的情况下是不会有问题的,但是如果你的系统读并发很高,那么会出现这样的情况:
imagepng
这时候,数据库里值为 2,缓存里面的值为 3,就出现数据不一致问题了。

那么这个问题怎么来解决呢?
可以通过数据库与缓存更新与读取操作进行异步串行化来解决这个问题
imagepng
更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部的队列中,读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据 + 更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部的队列中,一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行,这样的话,一个数据变更的操作,先执行,删除缓存,然后再去更新数据库,但是还没完成更新,此时如果一个读请求过来,读到了空的缓存,那么可以先将缓存更新的请求发送到队列中,此时会在队列中积压,然后同步等待缓存更新完成,这里有一个优化点,一个队列中,其实多个更新缓存请求串在一起是没意义的,因此可以做过滤,如果发现队列中已经有一个更新缓存的请求了,那么就不用再放个更新请求操作进去了,直接等待前面的更新操作请求完成即可,待那个队列对应的工作线程完成了上一个操作的数据库的修改之后,才会去执行下一个操作,也就是缓存更新的操作,此时会从数据库中读取最新的值,然后写入缓存中,如果请求还在等待时间范围内,不断轮询发现可以取到值了,那么就直接返回; 如果请求等待的时间超过一定时长,那么这一次直接从数据库中读取当前的旧值

该解决方案要注意的问题:
1、读请求长时阻塞
如果写操作很频繁,那么队列中会积压很多写操作,导致读请求超时,走数据库,这里一定要多模拟线上环境,看看你并发最高的时候,请求是多少,来多次模拟,如果发现读请求超时过多,那么你需要加机器,让更多的队列来处理写请求。
2、读请求并发量过高
这里也是,需要多次模拟不同的情况,看并发过高的时候,服务器是否可以抗住,不行就加机器。
3、多服务实例部署的请求路由
可能这个服务部署了多个实例,那么必须保证说,执行数据更新操作,以及执行缓存更新操作的请求,都通过 nginx 服务器路由到相同的服务实例上
4、热点数据的路由问题,导致请求的倾斜
万一某个数据的读写请求特别高,全部打到相同的机器的相同的队列里面去了,可能造成某台机器的压力过大;就是说,因为只有在数据更新的时候才会清空缓存,然后才会导致读写并发,所以更新频率不是太高的话,这个问题的影响并不是特别大。但是的确可能某些机器的负载会高一些,因为毕竟有些数据的访问就是高一些。

注:每个人的问题可能都不一样,以上方案不一定完全适合你,不过设计思想是可以参考的。

redis 缓存全量更新问题

imagepng

一般我们会把数据都以 json 格式存在 redis 里面,比如电商商品有分类、店铺信息、商品属性等等。如果分类变了,那需要把大 json 取下来,更新完,在保存到 redis 里面。这样的存储有几个不好的地方:
1、因为存储的数据比较大,所以网络开销比较大;
2、每次对 redis 做存取大数据,对 redis 的压力比较大;
3、数据本身的大小会影响 redis 的吞吐量和性能;

redis 缓存全量更新问题如何解决?
方法就是 redis 按维度化存储,把商品按照维度来拆分,比如商品分类,店铺信息、商品属性等,存储到 redis 的时候,也是按照维度来存储,这样原来你的 key 大小 200k,拆分完之后每个 key 的大小为 20k。大大提升了 redis 的性能和吞吐量。大大减少了网络资源的消耗,以及 redis 的压力。

imagepng

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1083 引用 • 3461 回帖 • 263 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 247 回帖 • 147 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
chaigx
欢迎关注我的公众号:程序之声。有些文章没办法同步过来,访问个人博客:http://www.chaiguanxin.com

推荐标签 标签

  • abitmean

    有点意思就行了

    31 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖 • 1 关注
  • 笔记

    好记性不如烂笔头。

    306 引用 • 782 回帖
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    332 引用 • 619 回帖 • 1 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 444 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 154 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    45 引用 • 25 回帖
  • 安装

    你若安好,便是晴天。

    131 引用 • 1184 回帖
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    175 引用 • 992 回帖
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 44 关注
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    51 引用 • 37 回帖 • 1 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    4 引用 • 91 回帖
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    536 引用 • 672 回帖
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 1 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    20 引用 • 245 回帖 • 234 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 45 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    54 引用 • 85 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    83 引用 • 165 回帖 • 13 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 110 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 4 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖 • 1 关注