单进程单线程的 Redis 如何能够高并发
1、基本原理
采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗)
为什么不采用多进程或多线程处理?
- 多线程处理可能涉及到锁
- 多线程处理会涉及到线程切换而消耗 CPU
单线程处理的缺点?
- 无法发挥多核CPU性能,不过可以通过在单机开多个 Redis 实例来完善
2、Redis 不存在线程安全问题?
- Redis 采用了线程封闭的方式,把任务封闭在一个线程,自然避免了线程安全问题,不过对于需要依赖多个 redis 操作的复合操作来说,依然需要锁,而且有可能是分布式锁
3、什么是多路 I/O 复用(Epoll)
网络 IO 都是通过 Socket 实现,Server 在某一个端口持续监听,客户端通过 Socket(IP+Port)与服务器建立连接(ServerSocket.accept),成功建立连接之后,就可以使用Socket中封装的InputStream和OutputStream进行IO交互了。针对每个客户端,Server都会创建一个新线程专门用于处理
默认情况下,网络IO是阻塞模式,即服务器线程在数据到来之前处于【阻塞】状态,等到数据到达,会自动唤醒服务器线程,着手进行处理。阻塞模式下,一个线程只能处理一个流的IO事件
为了提升服务器线程处理效率,有以下三种思路
非阻塞【忙轮询】:采用死循环方式轮询每一个流,如果有IO事件就处理,这样可以使得一个线程可以处理多个流,但是效率不高,容易导致 CPU 空转
Select 代理(无差别轮询):可以观察多个流的IO事件,如果所有流都没有IO事件,则将线程进入阻塞状态,如果有一个或多个发生了 IO 事件,则唤醒线程去处理。但是还是得遍历所有的流,才能找出哪些流需要处理。如果流个数为N,则时间复杂度为O(N)
Epoll 代理:Select 代理有一个缺点,线程在被唤醒后轮询所有的 Stream,还是存在无效操作。 Epoll 会哪个流发生了怎样的 I/O 事件通知处理线程,因此对这些流的操作都是有意义的,复杂度降低到了
O(1)
4、其它开源软件采用的模型
- Nginx:多进程单线程模型
- Memcached:单进程多线程模型
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论