一项公益坚持27年,雅诗兰黛为何如此执著(雅诗兰黛为什么能在中国成功)
10782023-08-24
老铁们,大家好,相信还有很多朋友对于单线程Redis性能为何如此之高和redis单线程为什么快的相关问题不太懂,没关系,今天就由我来为大家分享分享单线程Redis性能为何如此之高以及redis单线程为什么快的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!
本文目录
Redis的优势
性能高不仅跟线程模型有关,它有很多原因,主要有如下3点:
基于内存;单线程,但IO多路复用的利用率高;数据结构为高性能优化。下面分别阐述。Redis的优势:基于内存性能高低都是相对的,Redis是基于内存的数据库,相对的我们拿传统的基于磁盘的数据库进行对比,如图:
其中,Redis数据库基于内存,分场景如下:
数据查询类场景:内存中有全量的数据,可以直接从内存中取得;数据写入类场景:如果配置的是同步持久化,写入内存的同时,也会写入磁盘,性能有所降低,但是由于Redis使用的是IO多路复用,同时没有线程竞争,因此IO利用率很高。数据写入类场景:如果配置的是异步持久化,写入内存成功,即响应成功,不用等待磁盘的写入,性能很高。传统磁盘数据库,分场景如下:
数据查询类场景:从磁盘中索引数据,查询并返回响应;数据写入类场景:从将数据写入磁盘,同时更新磁盘中的索引文件。以上可以看出:Redis是基于内存的数据库,大多数操作在内存中完成,内存的IO效率比磁盘要高的多。因此,这是Redis性能高的一个原因。
Redis的优势:单线程,IO多路复用的IO利用率高Redis是单线程的,通常如果单线程处理效率不高,都开多线程处理,但是Redis这里为什么反到效率高了呢?
多线程存在线程竞争,且有锁的问题,多线程代码逻辑复杂,复杂的逻辑通常带来一定的性能损耗;Redis虽然是单线程,但是它的“I/O多路复用(multiplexing)”模型的IO利用率很高。Redis的“I/O多路复用”是采用的效率最高的epoll模式,单线程却实现了多客户端接入,以及高IO利用率。如下图:
Redis的优势:数据结构为高性能优化数据结构的优化主要有以下两点(篇幅有限,在这里就不展开了):
Redis全程采用了Hash结构,因此存取效率非常高;对于数据的存储内容也进行了压缩,节省了空间占用,也减少了io带宽。还有哪些原因导致了Redis的高性能,大家都是用的什么样的持久化策略,集群部署策略,都遇到哪些坑,Redis有哪些不足,欢迎在评论区留言讨论。我是闲谈架构,聚焦JAVA架构,持续输出,欢迎关注。1.
redis是基于内存的,内存的读写速度非常快;
2.
redis是单线程的,省去了很多上下文切换线程的时间;
3.
redis使用多路复用技术,可以处理并发的连接。非阻塞IO内部实现采用epoll,采用了epoll+自己实现的简单的事件框架
这得益于linux的IO多路复用
核心点应用层可以把多个socket连接注册给操作系统,让操作系统帮忙盯着这些socket有没有数据过来(可读/可写)。
注册完成之后,应用层就可以去干别的事了。当socket有数据过来时,操作系统会通知应用层,应用层再去处理。这样的优势在于应用层1个线程,就可以服务多个网络请求,即IO多路复用。
IO多路复用的具体实现模型有select/poll/epoll,目前epoll是性能最好的。
简单描述客户端和服务端是如何通过epoll读写数据的。一个网络程序,客户端A给服务端B发数据,A编写socket程序,调用writeAPI向这个socketfd写数据。
写完之后,数据怎么发给B呢?
是需要经过操作系统、网卡、网线发过去的。
A的操作系统把数据按照网络协议包装好,通过网卡发出去,经过网络线路,最终都到B了。
B谁先来处理?肯定是操作系统先拿到这些数据,它会先放在内核态,然后通知上层的应用,你的数据来了,你来读取吧。
epoll是操作系统提供的API,应用层把socket提前注册给操作系统,先调epoll的注册方法,这就托管给操作系统了。
然后应用层再调用epoll的wait方法,有fd有数据过来/可写,就返回,返回指的就是wait方法return了,应用层就拿到这个fd可以操作了。不返回说明,注册的这些fd都不能读写,那应用层就阻塞在wait上等着,除非wait方法传了个timeout参数,那就到了timeout也给应用层返回。
这是读的情况。除了读,还有写。写对应的是发数据,fd可以写了,就通知应用层,应用就写这个fd。
还是拿刚才A->B传输数据来说。刚才说的是读,是B要读A的数据。现在看A这一侧,A要写这个fd给B发数据。
一开始写,fd对应的是操作系统的缓冲区,A写fd,会先写到操作系统的缓冲区里,然后由操作系统把缓冲区的数据发给B。
但如果A一直写一直写,B那边读的慢,那A这边的缓冲区就会满了,满了之后应用层还在调write,肯定就不可以写了,那啥时再可以写?A操作系统能知道B那边有没有把缓冲区的数据读走,如果读走了,缓冲区空出来了,那A的操作系统就通知应用层说,缓冲区空出来了,你继续可以写了。
fd是操作系统封装的数据结构,但凡一个应用层要做网络交互,必须经过操作系统,所以操作系统就提供了很多高效的办法,比如缓冲区和这些通知机制。
说白了就是,操作系统是一个大管家,其目的就是为了更好地服务上层应用,所以它做了很多事,这些IO多路复用,都是操作系统在帮应用层干活。
因为,redis是单线程,然而,是可以同时有多个客户端访问的,每个客户端会有一个线程。客户端访问之间存在竞争。
由于存在多客户端并发,所以必须保证操作的原子性。比如银行卡扣款问题,获取余额,判断,扣款,写回就必须构成事务,否则就可能出错。
所以,redis单进程要加锁。在传统单体应用单机部署的情况下,可以使用Java并发相关的锁,如ReentrantLcok或synchronized进行互斥控制。
OK,关于单线程Redis性能为何如此之高和redis单线程为什么快的内容到此结束了,希望对大家有所帮助。