io与线程

tcp基础

tcp端口:

tcp/ip协议规定端口号(unsigned short),所以单机(0-65535)最大的端口号为655535(0是系统保留,所以最多可用端口号为65535个)

tcp连接:

是四元组表示(localip, localport, remoteip, remoteport),所以对server端主机来说ip:port是固定的,remoteip:port的数量决定可用连接上限为 2的32次方 * 2的16次方 (约280万亿个)

实际的tcp连接数:

对于tcp连接来说,每一个都要占有文件描述符及一定的内存(send/receive queue),

所以实际数量受系统配置(Linux ulimit)及内存的影响

IO通信

https://www.bilibili.com/video/BV1DP4y1Z769

1.连接指定端口

nc localhost 8080

2.查看网络端口状态

netstat -natp

3.跟踪内核方法调用情况

strace -ff -o out java SocketBIO

clone(child_stack=0xabcd)

4.多线程的栈是独立的,堆是共享的

proc/pid/task 可以看到多个子线程

proce/pid/fd 文件描述符

5.服务端使用内核提供的非阻塞参数,使用非阻塞方式处理socket连接

serverSocket.setNoBlocking(true);

socket = serverSocket.accept();// 此处不阻塞了,直接返回null或对象(-1或者fd)

每个socket(四元组)都有自己的接收和发送队列

所以此处不需要再新开线程了

6.socket设置非阻塞,使用socket.read/write()读写 (os recive/send函数)

多个clientSocket的话,遍历执行接口

BIO与NIO的有缺点:

①BIO必须新开线程才能处理新来的连接;(线程开销太多)

②NIO在有多个连接的情况下,只有一个连接需要收发数据(循环比较消耗cpu,而且多次系统调用)

7.多路复用器(谁有数据的状态)

同步io:指程序需要自己从queue内存copy数据(bio/nio/netty/多路复用器都是)

异步io: windows iocp

同步io多路复用器:select/poll/epoll

select: 传多个socket进去,返回只有收发数据的socket,然后只处理收发socket即可

epoll:

epoll_create()函数 创建一个内核空间,

epoll_ctl (内核空间地址, add socket, 监听的事件)

epoll_wait() 等待有事件

jdk里的Selecter是对os的(select、epoll优先使用epoll)封装,保证对外实现的一致性。

netty

使用strace跟踪redis/nginx的系统调用

redis

1.为什么用redis

高性能:快速响应用户请求(预热数据)、

高并发:减轻数据库压力(mysql最多2000并发、redis可以上万)、

问题/缺陷:

1.双写不一致

2.穿透缓存(redis宕机、缓存失效)

3.并发竞争

redis支持的数据类型

String String
hash字典 Map<String, Map>
List列表 LinkedList
Set 集合 HashSet 交集、并集、差集
ZSet有序集合 TreeSet

线程模型

快:基于内存、reactor线程模型

文件事件处理器:

1.多个socket

2.IO多路复用

3.文件时间分派器

4.时间处理器(连接应答、命令请求、命令回复)

过期策略

惰性删除、定期删除

内存淘汰策略

不淘汰、最近最少使用、过去时间(ttl)、随机删除、全局最少使用、全局随机删除

哨兵机制

减少redis不可用概率

单机redis –>

主从架构(手动将redis从节点设置为主节点) –>

哨兵模式(客户端–>哨兵节点获取主节点–>访问redis主节点获取数据–>主节点下线–>哨兵切换主从–>

通知客户端新的主节点–>从新的主节点获取数据)

哨兵选举:

缓存击穿、雪崩、穿透

击穿:热点数据突然失效(设置合适的过期时间或永不过期、互斥锁)

雪崩:大规模失效、多级缓存、互斥锁

穿透:查询不存在的、不会缓存的数据(缓存空对象、参数校验、布隆过滤器)

Redis持久化方案

1.RDB :

CUW机制(生成内存副本)

fork创建子进程备份:

自动触发(配置触发方式)、shutdown命令、flushall触发(会清空数据及dump文件)

手动触发:save命令(会阻塞当前redis进程)、bgsave命令(fork出的子进程来完成持久化)

2.AOF

3.混合持久化

AOF缓冲区 –》同步策略 –》生成base/inc文件 –》AOF重写–》二进制文件+inc