1.单线程
如果一个DB,CPU不是瓶颈,大多数时IO密集的,不是CPU密集的。具体到redis,如果不考虑持久化,不会有瓶颈,真正来源时网络IO,也就是客户端和服务端之间的网络传输延迟,因此redis选择了单线程的IO多路复用实现核心网络模型。
(1)避免过多的线程上下文切换开销;
(2)避免同步机制的开销,会涉及到底层数据同步的问题,要加同步比如锁。带来加锁和解锁。
(3)简单可维护,如果多线程,都必须实现线程安全,会更加复杂。
2.redis6.0引入多线程I/O
只是用来处理网络数据的读写命令和协议解析,而执行命令依旧是单线程。
为什么引入:单线程会导致系统浪费很多CPU在网络I/O上,降低吞吐量;多线程可以充分利用CPU资源,分摊IO读写负荷。效果翻倍。
方式:(1)优化网络IO;分为零拷贝技术或者DPDK技术,和利用多核优势;
零拷贝(Zero-copy)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。
零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率。减少了用户进程地址空间和内核地址空间之间因为上下文切换而带来的开销。
注意:零拷贝并不是不需要拷贝,只是减少不必要的拷贝次数与线程上下文切换次数。
(2)提高内存读写速度(硬件)
3.redis通信流程
4.redis的多线程实现机制
(1)主线程负责接受建立请求,获取socket放入队列
(2)主线程处理完读事件后,通过RR将连接分配给这些IO线程
(3)主线程阻塞等待IO读取socket完毕;
(4)主线程通过单线程方式执行请求命令,请求数据读取并解析完成,但不执行。
(5)主线程阻塞等待IO线程将数据回写socket。
特点:IO要不同时读,要不同时写,不会同时读写;IO只负责读写socket命令,不负责处理。
5.执行命令仍然是单线程顺序执行,不存在线程安全问题。
事务
1.并不是传统的事务,单个命令执行是原子性的,但是redis事务的执行并不是原子性的。
(1)是一个批量的脚本,中间指令的失败不会导致回滚,下面指令会继续做。严格意义上其事务不具备原子性。
(2)命令顺序执行,不会被其他客户端发送的命令请求打断;
(3)事务开启前,中断连接,服务器不会执行;但是如果中断在客户端执行EXEC命令后,那么该事务中所有命令都会被服务器执行。
2.事务的三个阶段
1.multi开启事务
2.指令入队
3.exec执行事务块内命令
4.discard取消事务
5.watch监视一个或多个key,如果事务执行前key,被改动,事务被打断。unwatch取消监视。
watch命令是个乐观锁,提高CAS,监控一直持续到exec命令。
3.redis单线程,事务总是有隔离性。
4.redis事务的其他实现
(1)基于LUA脚本,一次性按顺序执行;
(2)基于中间标记变量,标识事务是否执行完成。