当前位置: 首页 > 科技观察

和刚井聊Redis多线程

时间:2023-03-16 18:07:04 科技观察

周末被一个小同学拉黑很气愤。他要和我讨论redis是多线程的还是单线程的。这个问题比较好解释,但是我遇到的是野蛮人。答案很明显:redis6,逃不过真象定理,引入了多线程;但在redis6之前,它是单线程的。也就是说,这不是一个是和不是的问题,它是关于二次元的版本参与。可是,这个同学想打我的脸。不知道小姐姐的皮肤很嫩吗?我不能碰它。“按照你的逻辑,redis5是单线程的?”“是的。”“那下面的截图是怎么回事?”同学丢给我一张照片,给我一个鄙视的眼神。“用top-Hp查看,redis5有4个线程,怎么解释?”我不知道如何向他解释这个问题。用top命令观察,redis5必须是多线程的,比如bgsave、aof等,必须开线程操作,不然早就炸了。按照这个逻辑,redis从来就没有单一进程。看着这幅画,我陷入了无尽的悲痛之中。“Redis是否是单进程,主要是针对Redis的读写操作。”但是这句话是没有说服力的吧罚款。“写程序一定要严谨,你们这些人太不严谨了。多线程就是多线程,你应该问'redis的读写操作是不是多线程'”。我问你大头鬼。我不想再和他交流了,因为我为自己的博学感到羞愧。但他的下一个问题让我陷入了真正的沉思。1、redis多线程有多快?Redis多线程有哪些性能提升?官方的说法是:可以轻松加速两倍。速度加倍可能更容易。我的英文不是很好,对这个英文修改很是迷惑。既然容易,为什么还有可能。两次,到底是增加了2倍,还是增加到2倍。据官方介绍,能提升多少取决于硬件的能力。官方推荐,只有当你有4个CPU核心时,才有必要尝试这个多线程Feature。不要用土豪的眼光盯着我。这种4core的配置,已经秒杀大部分公司了。所以Redis贴心的关闭了多线程功能。(好像有点语法错误)只能求助于那些在一线的前同事了。他们在生产环境中使用过这种划时代的多线程Redis6x吗?结果让我很满意,没有!我对其中一个回复特别满意。他说:“你其实是在问我谁卡在JDK1.6,跑的是Windows版的Redis,有没有用过Redis6,我还在用Redis3。”我比较满意的是另一个答复,他说:滚!2.如何使用?新技术一定要吹捧,否则没人会去实践,作为追随者也只能吃。从理论上讲,多线程肯定会提高性能。一个爸爸挣钱和两个爸爸挣钱,效果自然不一样,苦的还是妈妈。Redis6开启了多线程,需要配置一个参数。当启用io-threads4时,只有出站流量使用多线程。如果您希望入站流量也使用多线程,您还可以配置以下参数。io-threads-do-readsyes就是这两个参数。可以看到现在的redis多线程还是有点寒酸。开启后,我们仍然使用top-Hp查看相关进程,可以看到多了3个io_thd进程。这部分逻辑在networking.c中实现。这个文件达到了3k多行,已经够庞大了。3、为什么Redis又要搞多线程了?使用redis-benchmark测试,单机单核吞吐量可达10w+。1秒是100亿纳秒,单次内存操作大约100纳秒,内存操作可以达到1000w/s的速度。Redis的瓶颈在哪里?使用perf进行跟踪,可以发现其耗时主要体现在sys_write系统调用,即向socket写入数据。既然找到了瓶颈,就把它优化掉。redis选择的方式是使用多线程。我使用基准测试它。在4核机器上,CPU满负荷运行时QPS达到16w,算不上翻倍(对比单核9w/s)。benchmark6379clients32164519.20requestspersecond165411.09requestspersecond用了这么强的硬件,却获得了如此有限的性能提升,并不令人满意。不难解释为什么现在修炼的人这么少。因为是新的,所以还是不够吸引人。毕竟4core的机器,如果我部署3个redis集群实例,理论上会增加3倍。在redis的配置文件中,有很多内容标注了这个新特性。4、如何实施?如图所示,一个redis请求需要建立连接,然后获取操作命令,然后执行命令,最后将响应结果写入socket。在redis的多线程模式下,获取、解析命令、输出结果这两个过程可以配置为多线程执行,因为毕竟是我们定位的主要耗时点。但是命令的执行,也就是内存操作,还是单线程运行的。这种设计创造了一个特点。Redis依然不存在多线程锁竞争和线程安全问题,因为它的数据读取步骤还是单线程的,需要排队运行。一些比较耗时的操作,比如keys*、hgetall等,还是需要注意一下。Redis不是传统的反应器模型。说实话,很多东西如果硬套在概念上,只能进头漏尾。它不是master,worker是一个类似于memcached的clean模型,因为它抽取了命令执行操作。原因看上图就够了。End那么,下一个吸引bar的问题来了:在这种多线程的应用场景下,redis是I/O密集型还是计算密集型?或许,如果redis是多线程的,无处不在的轮子如果属于“计算”的话,就可以看作是一个计算密集型的应用。