GVKun编程网logo

nodejs + redis/mysql 连接池问题(nodejs 数据库连接池)

1

对于nodejs+redis/mysql连接池问题感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解nodejs数据库连接池,并且为您提供关于2.redis和memcached有什么区别?re

对于nodejs + redis/mysql 连接池问题感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解nodejs 数据库连接池,并且为您提供关于2.redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发?、5.如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?、8. 了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?、Actix 和 DeadPool (Couchbase) 的 Rust 连接池问题的宝贵知识。

本文目录一览:

nodejs + redis/mysql 连接池问题(nodejs 数据库连接池)

nodejs + redis/mysql 连接池问题(nodejs 数据库连接池)

NodeJS

上图中,nodejs共有俩连接,分别发送查询请求到redis服务器上。因为redis是单线程作业,不管两个查询任务是由一个连接发来还是多个连接发来,也不管任务是串行一前一后先后发送到服务器,还是并行的同时发送到服务器上,redis都将他们一个个按顺序执行,并通过当前连接返回给客户端(这里是nodejs)。nodejs接受到redis的返回后,也管不了并行不并行,都得等他nodejs的主线程空闲的时候才能来一个个处理服务器返回的数据。

所以单从上面结论来看,nodejs + redis只需要公用一个连接就可以了,所以是不需要用连接池的。

再来看看nodejs + mysql下的情况

不同的是mysql不是单线程服务的,也就是它可以并行处理多个查询请求。

如上图所示,mysql会为每个连接创建一个单独的线程来查询。不同于redis数据基本都在内存中,因为mysql会有大量的读取磁盘的IO操作,所以多个线程一起工作会比一个个查询要快。

但是nodejs又是单线程的,它能不能同时发送多个请求到mysql服务器上呢?

这里要理解nodejs的运作,虽然nodejs是一个主线程,但是它调用的IO指令等是通过另外的线程去做的,IO指令完成后就给主线程一个小任务片,也就是回调函数了。

这里有个很关键的点就是,nodejs主线程一个,但是IO线程会有多个。

因此如果用nodejs + mysql只用单个连接的话那么就利用不到mysql能同时服务多个查询的优势了。应该使用类似下图的运作方式,nodejs 使用多个连接来连接mysql。多连接是需要连接池的,有连接池就避免了每次连接都要去创建销毁的消耗了。

所以我们第一步的感觉认为Nodejs是单线程而不是需要连接池是错误的,使用不使用连接池,不光看客户端,还要看数据库服务器等。要全盘理解整个系统的运作模式才能下结论。了解服务器的运作模式,有没有阻塞操作,是否是多线程等。我想redis设计成单线程主要原因在于它的数据基本都在内存中,查询数据过程总不会产生阻塞过程,cpu也不会处于空闲状态。

全局连接断开重连问题

到这里还没完。综上面的分析,nodejs + mysql用线程池是没什么问题的。nodejs + redis只用单个连接就够。不过也还是有人建议需要连接池。为了说明问题得从代码着手。我们使用node-redis这个包来做例子。

例如新建了一个db.js

var redis = require("redis"),client = redis.createClient(6379, "127.0.0.1");module.exports = client;
登录后复制

上面的连接会在程序启动载入完后就连接上了。使用它的时候引入它就可以使用全局唯一的连接。

var db = require("db.js");exports.add = function(req, res, next) { db.get("keyName", function() {res.send("ok");});}
登录后复制

这里于是有这样的问题存在。

但此处全局只有一个连接,并且这个连接是程序启动的时候创建的。它不同于连接池中的连接那样运行时候动态创建。如果某个时候唯一的连接断掉了,程序又不会动态去创建连接,岂不是需要重新启动服务器才行。

看是来挺可怕,但好在这个问题是不存在的。因为redis的客户端会自动重新连接,所以不需要重新启动服务器。

但是因为连接断开那一小段时间,应用服务器不能正常对外服务,但是连接自动重连是需要一定的时间间隔的。例如一秒之后,所以这一秒之内系统是处在不能服务状态。

也正是基于上面这样的原因,于是就有连接redis使用连接池的做法。如果使用连接池来管理,当连接不可用的时候立即手动去创建新连接。和自动重连相比,一个是手动立即重连,一个是等到一定间隔重连。相对来说手动重连的时间更短,也就是说系统那1秒中不能服务的状态或许可以缩短成0.5秒。于是就有了使用连接池管理redis连接的做法。严格来说这个不能算是连接池,而是一个连接管理模块。

到这里最后的结论nodejs + mysql使用连接池更好, nodejs + redis可以使用也可以不用。

2.redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发?

2.redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发?

作者:中华石杉

面试题

redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发?

面试官心理分析

这个是问 redis 的时候,最基本的问题吧,redis 最基本的一个内部原理和特点,就是 redis 实际上是个单线程工作模型,你要是这个都不知道,那后面玩儿 redis 的时候,出了问题岂不是什么都不知道?

还有可能面试官会问问你 redis 和 memcached 的区别,但是 memcached 是早些年各大互联网公司常用的缓存方案,但是现在近几年基本都是 redis,没什么公司用 memcached 了。

面试题剖析

redis 和 memcached 有啥区别?

redis 支持复杂的数据结构

redis 相比 memcached 来说,拥有更多的数据结构,能支持更丰富的数据操作。如果需要缓存能够支持更复杂的结构和操作, redis 会是不错的选择。

redis 原生支持集群模式

在 redis3.x 版本中,便能支持 cluster 模式,而 memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据。

性能对比

由于 redis 只使用单核,而 memcached 可以使用多核,所以平均每一个核上 redis 在存储小数据时比 memcached 性能更高。而在 100k 以上的数据中,memcached 性能要高于 redis。虽然 redis 最近也在存储大数据的性能上进行优化,但是比起 memcached,还是稍有逊色。

redis 的线程模型

redis 内部使用文件事件处理器 file event handler,这个文件事件处理器是单线程的,所以 redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 socket,将产生事件的 socket 压入内存队列中,事件分派器根据 socket 上的事件类型来选择对应的事件处理器进行处理。

文件事件处理器的结构包含 4 个部分:

  • 多个 socket
  • IO 多路复用程序
  • 文件事件分派器
  • 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将产生事件的 socket 放入队列中排队,事件分派器每次从队列中取出一个 socket,根据 socket 的事件类型交给对应的事件处理器进行处理。

来看客户端与 redis 的一次通信过程:

 

 

要明白,通信是通过 socket 来完成的,不懂的同学可以先去看一看 socket 网络编程。

首先,redis 服务端进程初始化的时候,会将 server socket 的 AE_READABLE 事件与连接应答处理器关联。

客户端 socket01 向 redis 进程的 server socket 请求建立连接,此时 server socket 会产生一个 AE_READABLE 事件,IO 多路复用程序监听到 server socket 产生的事件后,将该 socket 压入队列中。文件事件分派器从队列中获取 socket,交给连接应答处理器。连接应答处理器会创建一个能与客户端通信的 socket01,并将该 socket01 的 AE_READABLE 事件与命令请求处理器关联。

假设此时客户端发送了一个 set key value 请求,此时 redis 中的 socket01 会产生 AE_READABLE 事件,IO 多路复用程序将 socket01 压入队列,此时事件分派器从队列中获取到 socket01 产生的 AE_READABLE 事件,由于前面 socket01 的 AE_READABLE 事件已经与命令请求处理器关联,因此事件分派器将事件交给命令请求处理器来处理。命令请求处理器读取 socket01 的 key value 并在自己内存中完成 key value 的设置。操作完成后,它会将 socket01 的 AE_WRITABLE 事件与命令回复处理器关联。

如果此时客户端准备好接收返回结果了,那么 redis 中的 socket01 会产生一个 AE_WRITABLE 事件,同样压入队列中,事件分派器找到相关联的命令回复处理器,由命令回复处理器对 socket01 输入本次操作的一个结果,比如 ok,之后解除 socket01 的 AE_WRITABLE 事件与命令回复处理器的关联。

这样便完成了一次通信。关于 Redis 的一次通信过程,推荐读者阅读《Redis 设计与实现——黄健宏》进行系统学习。

为啥 redis 单线程模型也能效率这么高?

  • 纯内存操作。
  • 核心是基于非阻塞的 IO 多路复用机制。
  • C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快。
  • 单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。

5.如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?

5.如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?

作者:中华石杉

面试题

如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?

面试官心理分析

其实问这个问题,主要是考考你,redis 单机能承载多高并发?如果单机扛不住如何扩容扛更多的并发?redis 会不会挂?既然 redis 会挂那怎么保证 redis 是高可用的?

其实针对的都是项目中你肯定要考虑的一些问题,如果你没考虑过,那确实你对生产系统中的问题思考太少。

面试题剖析

如果你用 redis 缓存技术的话,肯定要考虑如何用 redis 来加多台机器,保证 redis 是高并发的,还有就是如何让 redis 保证自己不是挂掉以后就直接死掉了,即 redis 高可用。

由于此节内容较多,因此,会分为两个小节进行讲解。

  • redis 主从架构
  • redis 基于哨兵实现高可用

redis 实现高并发主要依靠主从架构,一主多从,一般来说,很多项目其实就足够了,单主用来写入数据,单机几万 QPS,多从用来查询数据,多个从实例可以提供每秒 10w 的 QPS。

如果想要在实现高并发的同时,容纳大量的数据,那么就需要 redis 集群,使用 redis 集群之后,可以提供每秒几十万的读写并发。

redis 高可用,如果是做主从架构部署,那么加上哨兵就可以了,就可以实现,任何一个实例宕机,可以进行主备切换。

8. 了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?

8. 了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?

作者:中华石杉

面试题

了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?

面试官心理分析

其实这是问到缓存必问的,因为缓存雪崩和穿透,是缓存最大的两个问题,要么不出现,一旦出现就是致命性的问题,所以面试官一定会问你。

面试题剖析

缓存雪崩

对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。

这就是缓存雪崩。

redis-caching-avalanche

大约在 3 年前,国内比较知名的一个互联网公司,曾因为缓存事故,导致雪崩,后台系统全部崩溃,事故从当天下午持续到晚上凌晨 3~4 点,公司损失了几千万。

缓存雪崩的事前事中事后的解决方案如下。

  • 事前:redis 高可用,主从 + 哨兵,redis cluster,避免全盘崩溃。
  • 事中:本地 ehcache 缓存 + hystrix 限流 & 降级,避免 MySQL 被打死。
  • 事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

redis-caching-avalanche-solution

用户发送一个请求,系统 A 收到请求后,先查本地 ehcache 缓存,如果没查到再查 redis。如果 ehcache 和 redis 都没有,再查数据库,将数据库中的结果,写入 ehcache 和 redis 中。

限流组件,可以设置每秒的请求,有多少能通过组件,剩余的未通过的请求,怎么办?走降级!可以返回一些默认的值,或者友情提示,或者空白的值。

好处:

  • 数据库绝对不会死,限流组件确保了每秒只有多少个请求能通过。
  • 只要数据库不死,就是说,对用户来说,2/5 的请求都是可以被处理的。
  • 只要有 2/5 的请求可以被处理,就意味着你的系统没死,对用户来说,可能就是点击几次刷不出来页面,但是多点几次,就可以刷出来一次。

缓存穿透

对于系统 A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。

黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。

举个栗子。数据库 id 是从 1 开始的,结果黑客发过来的请求 id 全部都是负数。这样的话,缓存中不会有,请求每次都 “视缓存于无物”,直接查询数据库。这种恶意攻击场景的缓存穿透就会直接把数据库给打死。

redis-caching-penetration

解决方式很简单,每次系统 A 从数据库中只要没查到,就写一个空值到缓存里去,比如 set -999 UNKNOWN。然后设置一个过期时间,这样的话,下次有相同的 key 来访问的时候,在缓存失效之前,都可以直接从缓存中取数据。

缓存击穿

缓存击穿,就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。

解决方式也很简单,可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。

Actix 和 DeadPool (Couchbase) 的 Rust 连接池问题

Actix 和 DeadPool (Couchbase) 的 Rust 连接池问题

如何解决Actix 和 DeadPool (Couchbase) 的 Rust 连接池问题

我正在尝试使用 couchbase-rs(couchbase rust 客户端)访问 couchbase 数据库。我使用的应用程序框架是 actix-web 和 deadpool 作为连接池管理器不受管理。我在 rust 中只获得 3k 性能,而在 java 中我获得 20k。我确信我在犯新手错误,并希望得到一些关于我可能做错了什么的指导。

源代码在 https://github.com/himanshumps/actix_demo.git 处,还有一个 github 操作可以为 CentOS/RHEL 生成二进制文件。

请帮帮我。

关于nodejs + redis/mysql 连接池问题nodejs 数据库连接池的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于2.redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发?、5.如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?、8. 了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?、Actix 和 DeadPool (Couchbase) 的 Rust 连接池问题的相关信息,请在本站寻找。

本文标签: