深入Redis(十)线程IO模型

线程IO模型

首先必须记住的是,Redis是个单线程程序。

为什么单线程还这么快?

Redis所有数据都在内存里,所有运算都是内存级别的运算,所以速度比在硬盘内操作更快。但是也正是由于是单线程,所以要小心使用那些时间复杂度O(n)的指令。

单线程如何处理那么多的并发客户端连接?

多路复用。

非阻塞IO

socket方法的读写默认都是阻塞的,在python中可以通过socket.socket().setblocking(False)来设置非阻塞IO。

时间轮询(多路复用)

非阻塞IO有个问题就是,线程读写数据可能只做了一部分就返回了,什么时候继续读数据,什么时候继续写数据,应该有个方法来通知它们。

时间轮询API就是来解决这个问题的,早期的select,后来的poll,现在的epoll和kqueque。

#基于select
import socket
import select
import queue

server = socket.socket()
server.bind((‘localhost‘, 8000))
server.listen()
server.setblocking(0)

msg = {}

inputs = [server]
outputs = []

while True:
    readable, writeable, exceptional = select.select(inputs, outputs, inputs)

    for r in readable:
        if r is server:
            conn, addr = r.accept()
            conn.setblocking(0)
            inputs.append(conn)
            msg[conn] = queue.Queue()
        else:
            try:
                data = r.recv(1024)
                msg[r].put(data)
                outputs.append(r)
            except ConnectionResetError:
                inputs.remove(r)
                continue

    for w in writeable:
        data = msg[w].get()
        w.send(data)
        outputs.remove(w)

    for e in exceptional:
        if e in outputs:
            outputs.remove(e)
        inputs.remove(e)
        del msg[e]
# 自动匹配版select,在linux中自动使用epoll,在windows中只能select,在bsd或mac中自动kqueue
import socket
import selectors

server = socket.socket()
server.bind((‘localhost‘, 8000))
server.listen()
server.setblocking(0)

sel = selectors.DefaultSlector()

def accept(server, mask):
    conn, addr = server.accept()
    conn.setblocking(0)
    sel.register(conn, mask, read)

def read(conn, mask):
    data = conn.recv(1024)
    if data:
        conn.send(data)
    else:
        sel.unregister(conn)
        conn.close()

sel.register(server, selectors.EVENT_READ, accept)

while True:
    events = sel.select()
    for key, mask in events:
        callback = key.data
        obj = key.fileobj
        callback(obj, mask)

不过这些都不用我们去实现,Redis内部已经替我们实现了这种轮询机制,只要记住多路复用是非阻塞IO,并不是异步操作。

原文地址:https://www.cnblogs.com/ikct2017/p/9503422.html

时间: 2024-10-10 00:05:24

深入Redis(十)线程IO模型的相关文章

通过实例理解Java网络IO模型

网络IO模型及分类 网络IO模型是一个经常被提到的问题,不同的书或者博客说法可能都不一样,所以没必要死抠字眼,关键在于理解. Socket连接 不管是什么模型,所使用的socket连接都是一样的.以下是一个典型的应用服务器上的连接情况.客户的各种设备通过Http协议与Tomcat进程交互,Tomcat需要访问Redis服务器,它与Redis服务器也建了好几个连接.虽然客户端与Tomcat建的是短连接,很快就会断开,Tomcat与Redis是长连接,但是它们本质上都是一样的.建立一个Socket后

Reids原理之IO模型

众所周知Redis是单进程单线程的应用,在如今多核横行的时代,我们不免有疑问,单线程的redis怎么就成了高性能的代表 当有多个线程同时调用redis的时候,那么单线程的redis是怎么处理的呢,这里就不得不说redis内部的IO模型 首先要提到几个概念,阻塞IO,非阻塞IO,同步IO,异步IO,多路复用 首先我们要理解IO的过程才能更好的理解上面这几种情况,IO分为两步,第一阶段是数据准备,第二阶段是数据复制阶段,所谓数据复制阶段就是讲数据从内核复制到用户空间 所谓阻塞IO,即我们传统的阻塞概

redis和memcached有什么区别?redis的线程模型是什么?为什么单线程的redis比多线程的memcached效率要高得多(为什么redis是单线程的但是还可以支撑高并发)?

1.redis和memcached有什么区别? 这个事儿吧,你可以比较出N多个区别来,但是我还是采取redis作者给出的几个比较吧 1)Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去.这大大增加了网络IO的次数和数据体积.在Redis中,这些复杂的操作通常和一般的GET/SET一样高效.所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是

Redis 和 Memcached 有什么区别?Redis 的线程模型是什么?为什么单线程的 Redis 比多线程的 Memcached 效率要高得多?

面试题 redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发? 面试官心理分析 这个是问 redis 的时候,最基本的问题吧,redis 最基本的一个内部原理和特点,就是 redis 实际上是个单线程工作模型,你要是这个都不知道,那后面玩儿 redis 的时候,出了问题岂不是什么都不知道? 还有可能面试官会问问你 redis 和 memcached 的区别,但是 memcached 是早些年各大互联网公司常用的缓存方案,但是现在近

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

作者:中华石杉 面试题 redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发? 面试官心理分析 这个是问 redis 的时候,最基本的问题吧,redis 最基本的一个内部原理和特点,就是 redis 实际上是个单线程工作模型,你要是这个都不知道,那后面玩儿 redis 的时候,出了问题岂不是什么都不知道? 还有可能面试官会问问你 redis 和 memcached 的区别,但是 memcached 是早些年各大互联网公司常用的缓存

线程,协程,IO模型

理论: 1.每创造一个进程,默认里面就有一个线程 2.进程是一个资源单位,而进程里面的线程才是CPU上的一个调度单位 3.一个进程里面的多个线程,是共享这个进程里面的资源的 4.线程创建的开销比进程要小,不用申请空间,只要基于现在的进程所在的空间,开一条流水线 就可以,所以创造线程的速度比创造进程的速度快 5.进程之间更多的是竞争关系,因为他们彼此之间是互相隔离的,而同一个进程的线程之间是合作关系 线程与进程的区别 1.同一进程内的线程共享创建它们的进程的地址空间,也就是同一进程内的多个线程共享

Cpython的进程,线程,协程,io模型

一.进程: 一  基础概念: 1.进程的定义: 进程本身是一个抽象的概念,进程是操作系统资源分配的基本单位,是正在进行的一个过程或者说一个任务,负责执行任务的是cpu. 2.并行与并发: 假设计算机只有一个cpu,由于一个cpu在同一时间只能执行一个任务,那么当有多个任务想同时运行按道理那么需要多个cpu执行 这个时候如果有多个cpu同时运行这些任务就是并行,如果是一个cpu运行多个任务(其实就是cpu在多个任务之间来回切换则为并发) 那么由此定义如下: 并行:多个任务同时运行,只有具备多个cp

5,线程池,进程池,协程,IO模型

今日内容: 1,线程池 2,进程池 3,协程 4,IO 模型 服务端要满足这三个条件: 1,24小时不间断的提供服务 2,能够支持高并发 3,要有固定的IP地址和端口在服务端这个地方会出现阻塞态情况: 阻塞IO 操作有: 1,链接循环 2,通信循环单线程实现高并发思路: 为了更好的提高程序的运行效率,即实现高并发,让服务端同时能够接受多个客户端的消息 所以一般在服务端会把,连接循环和通信循环封装为两个不同的函数方法, 这样当一个客户端与服务端进行通信时,服务端的连接循环可以和其他客户端进行连接,

进程池与线程池、协程、协程实现TCP服务端并发、IO模型

进程池与线程池.协程.协程实现TCP服务端并发.IO模型 一.进程池与线程池 1.线程池 ''' 开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少 在计算机能够承受范围内最大限度的利用计算机 什么是池? 在保证计算机硬件安全的情况下最大限度的利用计算机 池其实是降低了程序的运行效率,但是保证了计算机硬件的安全 (硬件的发展跟不上软件的速度) ''' from concurrent.futures import ThreadPoolExecutor import time p