第一章:NoSQL概述
1、Nosql背景
1.1、单机Web的弊端
要说到NoSQL产生的背景就不得不提存储数据的问题了。数据早期实际是以文件之类的形式存储在物理磁盘上,每次读写都会产生物理磁盘的I/O操作,开销很大,为了解决这个问题,数据库存储数据的方式出现了,所以然后都是使用关系性数据库,如MySQL。
Web1.0发展初期,关系型数据库作为一个标准,那时会这个牛X的不得了,单机Web【1个web服务器,1个数据库】面对用户访问量不是很多的情况下,可以自豪地说,我扛得住。
随着用户访问量的不断增加,使用关系型数据库的网站多多少少都遇到了瓶颈,比如
- 数据量增加到一定程度,单机数据库就放不下了
- 数据量暴增,超过300万,一定会给数据建立索引(B+ Tree),一个机器内存也存放不下
- 访问量变大后(读写混合),一台服务器承受不住。
总的来说,服务器和CPU面临巨大的内存压力、数据库服务器也承受着大量的I/O压力。随着互联网的不断发展,业务需求的多样化,大数据时代的到来,高并发问题的出现,Web的考验急剧增大,对技术的要求是越来越高。为了解决问题,MySQL不断优化,但仍旧遇到新的问题。Mysql的优化过程大致经历了以下几个过程:
- 优化数据库的数据结构和索引(难度大)
- 文件缓存,通过IO流获取比每次都访问数据库效率略高,但是流量爆炸式增长时候,IO流也承受不了
MemCache,当时最热门的技术,通过在数据库和数据库访问层之间加上一层缓存,第一次访问时查询数据库,将结果保存到缓存,后续的查询先检查缓存,若有直接拿去使用,效率显著提升。
1.2、解决数据库服务器大量的I/O压力
随着数据量的增加,利用关系型数据库来进行数据的I/O操作效率会很低下,且操作不方便,针对这个问题,也有一些原始方案,比如对数据库和表使用水平切分、垂直切分、读写分离等技术,但是这些方式是通过破坏一定的业务逻辑来换取性能提高的,有缺点不适用,原始的一些方案如下:(解决数据库服务器的瓶颈就是解决其读写效率)
法1(解决读的压力):Memcached(缓存) + Mysql + 垂直拆分(读写分离)
在数据库和数据库访问层之间加上一层缓存,同时布置多台数据库服务器(如下图),并对这3台数据库服务器各自的功能进行垂直拆分,即Mysql2负责写数据,而Mysql1和Mysql3负责读数据,同时3台数据库服务器之间要保持同步,这样才能保证我们三台数据库服务器里面的内容保持一致性。
当然在现在的技术看来,我们可以使用我们的数据库中间件mycat等来进行读写分离、分库分表的操作,但是这都是后话,当前阶段考虑使用缓存技术(redis之前,多数使用的Memcached作为缓存)和同步机制来实现,即从Mysql数据库读取的内容先向缓存中保存一份,下次读的时候直接从缓存中拿
通过这样的操作,让三台数据库分担了数据库的IO压力,网站80%的情况都是在读,每次都要去查询数据库的话就十分的麻烦!所以说我们希望减轻数据库的压力,我们可以使用缓存来保证效率!
法2(解决写的压力):分库分表 + 水平拆分 + Mysql集群
- 早些年:MyISAM:表锁,影响效率,高并发下就会出现严重的锁问题
- Innodb:行锁
- 慢慢的就开始使用分库分表来解决写的压力
理想的解决方案:
使用NOSQL数据库作为缓存数据库(主要就是指Redis),每次操作将数据放在缓存里面,极大减少IO操作,且提高查询的速度。另外,对于一些特有的一些数据格式(比如用户定位数据,歌曲数据等,传统关系型数据库不能处理),也可以使用NOSQL数据库作为列式数据库、文档数据库来进行管理。
1.3、解决服务器和CPU面临的巨大内存压力
对web服务器做一个集群管理或者分布式部署【多台服务器】,在服务器前面添加一个负载均衡或者反向代理服务器【Nginx】,比如当客户端对服务器发起多个查找数据的请求时,首先Nginx会把这个请求平均分担到多个服务器中,然后服务器访问数据库服务器进行查找,当然这时候我们的数据库服务器也面临这大量的I/O压力,解决办法如上所示。
回归正题,这种集群管理或者分布式的架构会产生一个最典型的问题---Session共享问题,即session应该怎么存储?
问题描述如下:首先,我们在服务器1上进行访问登录了,将用户登录信息保存到了当前服务器1的Session对象中,这时候,我们再次进行访问,发起一个登陆请求,因为负载均衡的缘故,比如这时候就访问了服务器2,这时候因为Session对象在服务器1里面,服务器2肯定没有该Session对象,就不能证明处于登陆状态,就不能进行后面的操作了。
以下有4个方案:
- 存储到客户端cookie,安全性不高
- 存在文件服务器或关系数据库里面:大量的I/O效率问题
- session复制,造成数据冗余,节点越多浪费越大
- 使用Nosql数据库,将用户登录信息存储到Nosql数据库,数据不需要存储到磁盘中,而是在内存中,读的速度更快
图解:
1.4、当前经典架构
如今信息量井喷式增长,各种各样的数据出现(用户定位数据,图片数据等),大数据的背景下关系型数据库(RDBMS)无法满足各种各样的大量数据的各种存储要求。因此现在一个基本的互联网项目,必须在此基础之上考虑非常多的细节,比如考虑缓存(Nosql-redis),文件存储等。目前一个基本的互联网项目:
2、NoSQL概述
2.1、什么是NoSQL
上面我们也提到关系型数据库的一些不足,并且提到用来充当缓存数据库的NoSQL数据库可以解决数据库服务器的IO压力(主要就是指Redis),并且也提到了NoSQL数据库可以解决web服务器集群布置带来的一些Session共享问题,同时也说到了NOSQL数据库也可以作为列式数据库、文档数据库等来进行一些特殊数据的管理。
如今各种各样的数据出现(用户定位数据,图片数据等),大数据的背景下关系型数据库(RDBMS)无法满足各种各样的大量数据的各种存储要求,但是Nosql数据库就能轻松解决这些问题。
下面来具体说一下NOSQL数据库
NoSQL = not only SQL,意思即不仅仅是SQL,泛指非关系型数据库,NoSQL不依赖业务逻辑方式存储,而是简单的key-value模式(Redis就是键值对存储的NoSQL)存储,并且增加了数据库的扩展能力。如果作为缓存数据库(Redis就是NoSQL作为缓存数据库的一种体现),则完全在内存中,速度快,数据结构简单
NoSQL泛指非关系型数据库,随着web2.0互联网的诞生,传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区,暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的。
2.2、为什么要用NoSQL
用户的个人信息,社交网络,地理位置。用户自己产生的数据,用户日志等等爆发式增长!这时候我们就需要使用NoSQL数据库的,Nosql可以很好的处理以上的情况!
关系型数据库:列+行,同一个表下数据的结构是一样的。
非关系型数据库:数据存储没有固定的格式,并且可以进行横向扩展。
2.3、NoSQL特点:
- 不遵循SQL标准
- 不支持ACID 【不是不支持事务】
- 远超SQL性能
- 方便扩展(数据之间没有关系,很好扩展!)
- 大数据量高性能(Redis一秒可以写8万次,读11万次,NoSQL的缓存记录级,是一种细粒度的缓存,性能会比较高!)
- 数据类型是多样型的!(不需要事先设计数据库,随取随用)
2.4、传统的RDBMS和NoSQL
传统的 RDBMS(关系型数据库)
- 结构化组织
- SQL
- 数据和关系都存在单独的表中 row col
- 操作,数据定义语言
- 严格的一致性
- 基础的事务
- ...
Nosql
- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性
- CAP定理和BASE
- 高性能,高可用,高扩展
- ...
2.5、(大数据时代)NoSQL应用场景
- 对数据高并发读写
- 大数据背景下海量(Velume)数据、多样性数据(Variety)、实时数据(Velocity)读写
- 对数据高可扩展性的
大数据时代的3高: 主要是对程序的要求
- 高并发
- 高可扩
- 高性能
真正在公司中的实践:NoSQL + RDBMS 一起使用才是最强的。
NoSQL不适用场景
- 需要事务支持
- 基于sql的结构化查询存储,处理复杂的关系,需要即席查询。
- 用不着sql的和用了sql也不行的情况,请考虑用NoSql
2.6、NoSQL数据库种类的四大分类
常用的NoSQL数据库:
KV键值对:
- 新浪:Redis
- 美图:Redis+Tair
- 阿里,百度:Redis+memcache
文档型数据库(bson和json格式一样):
- MongoDB
- 基于分布式文件存储的数据库,C++编写
- 是一个介于关系型数据库和非关系型数据库中中间的产品,是非关系型数据库中功能最丰富,最像关系型数据库的。值是类似Json的bson格式,因此可以存储比较复杂的数据类型
- 存储在集合中的文档,被存储为键值对的形式,键用于唯一标识一个文档,为字符串类型,值则可以是各种复杂的文件类型,我们称这种存储形式为BSON。
行式数据库(大数据时代)
定义:存储格式按照行的方式把一行各个字段的数据存储在一起,一行行连续存储。
列式数据库
- Hbase:HBase是Hadoop项目中的数据库,它用于需要对大量的数据进行随机、实时读写操作
- 分布式文件系统
- Cassandra:Apache Cassandra是一款免费的开源NoSQL数据库,其设计目的在于管理由大量商用服务器构建起来的庞大集群上的海量数据集(数据量通常达到PB级别)
图关系数据库 Neo4j等
- 主要用于:社会关系,公共交通网络,地图及网络拓扑
四者对比
2、Redis概述
2.1、Redis是什么?
Redis(Remote Dictionary Server ),即远程字典服务。redis是互联网发展的产物,作为key—value的高效存储系统,为互联网应用提供高效的解决方案。redis基于c语言开发,并且提供了基本的数据结构list、set、map,还支持java、c++、.net等众多语言API调用。redis存储的数据一般放在内存当中,这样加快了读取速度。是一个是开源的、高性能的、基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同场景下的缓存与存储需求。如Reids可以胜任消息队列、任务队列等不同的角色。
2.2、Redis能干什么?
- 内存存储、持久化,内存是断电即失的,所以需要持久化(RDB、AOF)
- 高效率、用于高速缓冲
- 发布订阅系统,消息队列、任务队列
- 地图信息分析
- 计时器、计数器(eg:浏览量)
- 。。。
2.3、Redis特性
Redis支持网络、可基于内存亦可持久化,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此基础上,Redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。并且在此基础上实现了master-slave(主从)同步。概括如下:
- 速度快
- 具有基于键值对的数据结构服务器
- 丰富的功能(如对列、订阅、流水线、事物等)
- 简单稳定
- 支持多种编程语言
- 多样的数据类型
- 持久化
- 主从复制
- 集群:高可用、分布式、高并发
- 非关系数据库不支持ACID ,不是不支持事务
2.4、redis经常使用的场景
1、排队使用
许多网站有秒杀、抢购的功能,这种功能即时性非常强,需要用高效的机制,发布库存的时候,可以把库存信息存在redis,这样用户购买后redis就减少,这样就不会造成短时间的阻塞(实时性)。
2、异步通信
服务A作为生成者,服务B作为消费者,可以代替笨重的webservice或者http,高效的作为服务之间的通信。
3、日志记录
redis与logstash使用,处理了分布式日志系统问题。logstash的agent收集日志发送到redis,另外一台中央logstash从redis读取日志,集中处理。
可以更加全面的概述为:
- 配合关系型数据库做高速缓存
- 高频次,热门访问的数据,降低数据库IO
- 分布式架构,做session共享
- 多样的数据结构存储持久化数据
3、Redis安装
3.1、下载Redis安装包
Redis官方网站:redis.io
界面如图所示:下载最新稳定版本6.2.6
下载后,安装包如下:
3.2、Linux下安装
直接利用xftp软件上传到opt目录下(也可以opt目录下创建一个文件夹用于解压)
xshell远程登录输入以下解压命令进行解压
1、进入opt目录可以看见我们的安装包
2、使用tar -zxvf redis-6.2.6.tar.gz命令进行Redis安装包的解压,解压目录可以自定义,这里直接解压在当前目录下,即/opt/redis-6.26
3、进入解压目录
4、运行下面命令进行编译和安装
make //编译
make install //安装
5、注意点:
如果没有准备好C语言编译环境,make命令会报错 —Jemalloc/jemalloc.h:没有那个文件
解决方案:是否安装了gcc,即查看版本号
[root@HDU001 opt]# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)
Copyright © 2015 Free Software Foundation, Inc.
本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;
包括没有适销性和某一专用目的下的适用性担保。
3.3、判断是否安装成功
查看默认安装目录:/usr/local/bin,里面有安装完成的Redis相应文件说明安装成功
进入该目录运行以下几个命令测试
redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何
redis-check-aof:修复有问题的AOF文件,rdb和aof后面讲
redis-check-dump:修复有问题的dump.rdb文件
redis-sentinel:Redis集群使用
redis-server:Redis服务器启动命令
redis-cli:客户端,操作入口
3.4、启动Redis服务
1、前台启动,命令行窗口不能做其他操作和关闭,否则服务器停止
cd /usr/local/bin
redis-server
2、后台启动(推荐)
备份redis.conf:拷贝一份redis.conf配置文件到其他目录(可以自定义创建一个),这里使用默认的/etc目录,以后就是用这个配置文件了
cp /opt/redis-6.2.6/redis.conf /etc
设置redis.conf配置文件(etc下的)中daemonize no改成yes:保存退出,让服务在后台启动:vim /etc/redis.conf
启动Redis
[root@HDU001 /]# cd /usr/local/bin //进入默认安装目录
[root@HDU001 bin]# redis-server /etc/redis.conf //通过配置文件启动
[root@HDU001 bin]# ps -ef|grep redis //查看进程,是否在运行。可以看见端口号为6379
root 13958 1 0 23:31 ? 00:00:00 redis-server 127.0.0.1:6379
root 13964 9143 0 23:32 pts/0 00:00:00 grep --color=auto redis
或者直接使用端口号来启动当前Redis服务
[root@HDU001 bin]# redis-cli -p 6379 #使用redis客户端进行连接
127.0.0.1:6379>
3.5、关闭Redis服务
[root@HDU001 bin]# redis-cli shutdown #使用redis客户端进行关闭
也可以进入客户端以后在进行关闭
[root@HDU001 bin]# redis-cli -p 6379 #使用redis客户端进行连接
127.0.0.1:6379> shutdown
not connected>
也可以直接指定端口号关闭或者kill -9 进程号
第5节:redis-benchmark:性能测试
5.1、redis-benchmark简介
- redis-benchmark 是一个压力测试工具。
- 官方自带的性能测试工具
Redis 性能测试是通过同时执行多个命令实现的。
语法
redis 性能测试的基本命令如下:
redis-benchmark [option] [option value]
注意:该命令是在 redis 的默认安装目录下执行的,而不是 redis 客户端的内部指令。
redis 性能测试工具可选参数如下所示:
| 序号 | 选项 | 描述 | 默认值 |
|---|---|---|---|
| 1 | -h | 指定服务器主机名 | 127.0.0.1 |
| 2 | -p | 指定服务器端口 | 6379 |
| 3 | -s | 指定服务器 socket | |
| 4 | -c | 指定并发连接数 | 50 |
| 5 | -n | 指定请求数 | 10000 |
| 6 | -d | 以字节的形式指定 SET/GET 值的数据大小 | 2 |
| 7 | -k | 1=keep alive 0=reconnect | 1 |
| 8 | -r | SET/GET/INCR 使用随机 key, SADD 使用随机值 | |
| 9 | -P | 通过管道传输 请求 | 1 |
| 10 | -q | 强制退出 redis。仅显示 query/sec 值 | |
| 11 | --csv | 以 CSV 格式输出 | |
| 12 | -/(L 的小写字母) | 生成循环,永久执行测试 | |
| 13 | -t | 仅运行以逗号分隔的测试命令列表。 | |
| 14 | -/(i 的大写字母) | Idle 模式。仅打开 N 个 idle 连接并等待。 |
5.2、使用
1、以下实例同时执行 10000 个请求来检测性能:
$ redis-benchmark -n 10000 -q
PING_INLINE: 141043.72 requests per second
PING_BULK: 142857.14 requests per second
SET: 141442.72 requests per second
GET: 145348.83 requests per second
INCR: 137362.64 requests per second
LPUSH: 145348.83 requests per second
LPOP: 146198.83 requests per second
SADD: 146198.83 requests per second
SPOP: 149253.73 requests per second
LPUSH (needed to benchmark LRANGE): 148588.42 requests per second
LRANGE_100 (first 100 elements): 58411.21 requests per second
LRANGE_300 (first 300 elements): 21195.42 requests per second
LRANGE_500 (first 450 elements): 14539.11 requests per second
LRANGE_600 (first 600 elements): 10504.20 requests per second
MSET (10 keys): 93283.58 requests per second
2、以下实例我们使用了多个参数来测试 redis 性能:
$ redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q
SET: 146198.83 requests per second
LPUSH: 145560.41 requests per second
以上实例中主机为 127.0.0.1,端口号为 6379,执行的命令为 set,lpush,请求数为 10000,通过 -q 参数让结果只显示每秒执行的请求数。
3、要求:100个并发连接、100,000 个请求,我们使用了多个参数来测试 redis 性能:
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
查看打印的信息:以set为例
4、其他测试:
1、redis-benchmark -h 192.168.1.201 -p 6379 -c 100 -n 100000
100个并发连接,100000个请求,检测host为localhost 端口为6379的redis服务器性能
2、redis-benchmark -h 192.168.1.201 -p 6379 -q -d 100
测试存取大小为100字节的数据包的性能
3、redis-benchmark -t set,lpush -n 100000 -q
只测试某些操作的性能
4、redis-benchmark -n 100000 -q script load "redis.call('set','foo','bar')"
只测试某些数值存取的性能
第6节:Redis相关知识介绍
6.1、数据库
数据库个数
Redis 默认有 16 个数据库,可以进入 redis.conf 文件查看,并且类似数组下标从0开始,初始默认使用0号库,统一密码管理,所有库同样密码
切换数据库
可以使用 select 进行切换数据库查看,如下
[root@HDU001 bin]# redis-cli -p 6379 #使用redis客户端进行连接
127.0.0.1:6379>select 8
127.0.0.1:6379[8]>
数据库大小
使用 DBSIZE 查看当前数据库的key的数量
127.0.0.1:6379[8]>DBSIZE #0
插入一个值后的数据库大小
127.0.0.1:6379[8]>set name haha
127.0.0.1:6379[8]>DBSIZE #1
数据库中的所有 Key
使用 keys * 查看
清空数据库
清空当前库 FLUSHDB
清空所有的库 FLUSHALL
6.2、端口号
默认端口号 :6379,为什么会取为 6379 呢?
6379 是 "MERZ" 九宫格输入法对应的数字。Alessia Merz 是一位意大利舞女、女演员。Redis 作者 Antirez 早年看电视节目,觉得 Merz 在节目中的一些话愚蠢可笑,Antirez 喜欢造“梗”用于平时和朋友们交流,于是造了一个词 “MERZ”,形容愚蠢,与 “stupid” 含义相同。后来 Antirez 重新定义了 “MERZ”,形容”具有很高的技术价值,包含技艺、耐心和劳动,但仍然保持简单本质“。到了给 Redis 选择一个数字作为默认端口号时,Antirez 没有多想,把 “MERZ” 在手机键盘上对应的数字 6379 拿来用了。
6.3、Redis 是单线程的
Redis 是很快的,它是基于内存操作的,所以 CPU 并不是 Redis 的性能瓶颈,它的瓶颈是机器的内存和网络带宽。所以既然可以使用单线程来实现,就直接设计为单线程了,没必要设计为多线程
为什么单线程还这么快?
- 误区:高性能的服务器一定是多线程的,多线程一定比单线程效率高(多线程会涉及到 CPU 的上下文切换,会消耗资源)
- 核心:Redis 把所有的数据都放在内存中的,所以单线程操作效率最高。对于内存系统来说,没有上下文切换效率就是最高的。 多次读写都在一个 CPU 上,在内存情况下,这就是最佳方案
- 总结如下:
- 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
- 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
- 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
- 使用多路I/O复用模型,非阻塞IO;
- 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
6.4、Redis是单线程+多路IO复用技术(multiplexing)
IO多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回执行,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池),就是说多路IO复用起到一个监听的效果,就绪后,Redis直接执行,不需要等待。
IO多路复用即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型
-
阻塞lO(串行):给女神发一条短信,说我来找你了,然后就默默的一直等着女神下楼,这个期间除了等待你不能做其他事情
-
非阻塞IO:给女神发短信,如果不回,接着再发,一直发到女神下楼,这个期间你除了发短信等待不会做其他事情
-
IO多路复用:是找一个宿管大妈来帮你监视下楼的女生(大妈等待),这个期间你可以些其他的事情。例如可以顺便看看其他妹子,玩玩王者荣耀,上个厕所等等,然后监视到了女神就通知你过来
串行 vs 多线程+锁(memcached) vs 单线程+多路IO复用(Redis)
-
串行:阻塞IO,一件事一件事的做,在做当前事时,不能做其他事,直到这件事情做完才做下一件事情,有等待
-
采用多线程+锁:略
-
单线程+多路IO复用:开启一个单线程(比如内核线程)做某件事情需要一定的时间,因此利用多路IO复用技术可以监视单线程做这件事(此时用户监听线程处于阻塞状态,而用户主线程可以继续发请求),在单线程去做这件事情的时候,我们可以做其他的事,当时间结束后返回响应数据,IO多路复用中用户线程监听功能就会监测到这个就绪状态,从而通知我们Redis(用户线程)返回来直接执行。通俗来说,3个人找黄牛【监听】帮忙去火车站买票,黄牛去买票的过程就是一个单线程过程,在黄牛这个单线程去买票的过程中,这3人不需要一直等待,可以做自己的事情。如果黄牛帮第2个人买到了它需要的票,则通知这个人票买好了,他就过来取票,而其他人继续可以做自己的事情,也是不需要一直等待,这就是多路复用
多路IO复用技术类似于拨开关,多个任务通过拨开关的方式共用一条线程【用户线程】,哪个任务需要这个线程了,开关就拨到哪个任务,避免了CPU在不同的线程中切换,提高效率。
IO复用又包括select, poll, epoll模式那么它们的区别是什么?
多路IO复用有select,poll,epoll这些模式。select监测数量能力有限。poll监测数量没有限制,但是需要一个一个核查。epoll监测数量没有限制,也不需要一个一个核查,直接看是否有一个正确的标识。
IO多路复用模型将用户socket对应的fd注册进epoll,然后epoll帮你监听哪些socket上有消息到达,这样就避免了大量的无用操作。此时的socket应该采用非阻塞模式。这样,整个过程只在调用select、poll、epoll这些调用的时候才会阻塞,收发客户消息是不会阻塞的(这就是所谓的异步阻塞),整个进程或者线程就被充分利用起来,这就是事件驱动,所谓的reactor模式。
- select: 一个女生下楼, select大妈都不知道这个是不是你的女神,她需要一个一个询问,并且select大妈能力还有限,最多一次帮你监视1024个妹子
- poll: 大妈不限制盯着女生的数量,只要是经过宿舍楼门口的女生,都会帮你去问是不是你女神
- epoll:大妈不制盯着女生的数量,并且也不需要一个一个去问,那么如何做呢? epol1大妈会为每个进宿舍楼的女生脸上贴上一个大字条,上面写上女生自己的名字,只要女姓下楼了,epoll大妈就知道这个是不是你女神了,然后大妈再通知你.
(与Memcache三点不同: Redis支持多数据类型,支持持久化,单线程+多路IO复用)