redis 主节点 从节点 关系_redis为什么引入多线程

redis 主节点 从节点 关系_redis为什么引入多线程这里的Redis主从结构可以是简单的主从,sentinel,redis cluster中的主从等。wait命令的作用:此命令将阻塞当前客户端,直到当前Session连接(主节点上)所有的写命令都被传送

Redis主从结构主节点执行写入后wait命令对性能的影响

这里的Redis主从结构可以是简单的主从,sentinel,redis cluster中的主从等。

wait命令的作用:
此命令将阻塞当前客户端,直到当前Session连接(主节点上)所有的写命令都被传送到指定数据量的slave节点。
如果到达超时(以毫秒为单位),则即使尚未完全传送到达指定数量的salve节点,该命令也会返回(成功传送到的节点的个数)。
该命令将始终返回确认在WAIT命令之前发送的写命令的副本数量,无论是在达到指定数量的副本的情况下,还是在达到超时的情况下。
具体说就是:比如对于1主2从的结构,Wait要求3秒钟之内传送到2个节点,但是达到超时时间3秒钟之后只成功传送到了1个slave节点上,此时wait也不会继续阻塞,而是返回成功传送的节点个数(1)。
有点类似于MySQL的半同步复制,但是效果完全不能跟半同步相比,因为Redis本身没有回滚的功能,这里的wait命令发起之后,即便是超时时间之后没有送到任何一个slave节点,主节点也不会回滚。
wait命令无法保证Redis主从之间的强一致,不过,在主从、sentinel和Redis群集故障转移中,wait能够增强(仅仅是增强,但不是保证)数据的安全性。

既然wait命令在当前连接之后会等待指定数量的从节点确认,其主节点的写入效率必然会收到一定程度的影响,那么这个影响有多大?
这里做一个简单的测试,环境2核4G的宿主机,docker下的集群3主3从的Redis集群,因此不用考虑网络延迟,在执行写入操作之后,使用两个Case,对比使不使用wait命令等待传送到salve的效率,
1,单线程循环写入100000个key值
2,多线程并发,10个线程每个线程写入10000个key,一共写入100000个key

Case1:单线程循环写入100000个key值
结论:不使用wait命令,整体耗时33秒,集群中单个节点的TPS为1000左右;使用wait命令,整体耗时72秒,集群中单个节点的TPS为480左右,整体效率下降了50%多一点

单线程不使用WAIT

redis 主节点 从节点 关系_redis为什么引入多线程

单线程使用WAIT(redis_conn.execute_command(“wait”, 1, 0))

redis 主节点 从节点 关系_redis为什么引入多线程

 

Case2:多线程循环写入100000个key值
结论:不使用wait命令,整体耗时19秒,集群中单个节点的TPS为1700左右;使用wait命令,整体耗时36秒,集群中单个节点的TPS为900左右,整体效率与单线程基本上一致,下降了50%多一点

多线程不使用WAIT,单节点上TPS可达到1700左右

redis 主节点 从节点 关系_redis为什么引入多线程

多线程使用WAIT,单节点上TPS可达到850左右

redis 主节点 从节点 关系_redis为什么引入多线程

鉴于在多线程模式下,CPU负载接近于瓶颈,因此不能再加更多的线程数,测试数据也仅供参考。

redis 主节点 从节点 关系_redis为什么引入多线程

 

总结:
wait能够在主节点写入命令之后,通过阻塞的方式等待数据传送到从节点,wait能够增强(但不保证)数据的安全性。
其代价或者说性能损耗也是不小的,通过以上测试可以看出,即便是不考虑网络传输延迟的情况下,其性能损耗也超出了50%。

#!/usr/bin/env python
# coding:utf-8
import sys
import time
import datetime
from rediscluster import StrictRedisCluster
import threading
from time import ctime,sleep


def redis_cluster_write():
    redis_nodes = [ {"host":"172.18.0.11","port":8888},
                    {"host":"172.18.0.12","port":8888},
                    {"host":"172.18.0.13","port":8888},
                    {"host":"172.18.0.14","port":8888},
                    {"host":"172.18.0.15","port":8888},
                    {"host":"172.18.0.16","port":8888}]
    try:
        redis_conn = StrictRedisCluster(startup_nodes=redis_nodes,password="******")
    except Exception:
        raise Exception
    redis_conn.config_set("cluster-require-full-coverage", "yes")
    counter = 0
    for i in range(0,100000):
        counter = counter+1
        redis_conn.set("key_"+str(i),"value_"+str(i))
        #redis_conn.execute_command("wait", 1, 0)
        if counter == 1000:
            print("insert 1000 keys "+str(str(datetime.datetime.now())))
            counter = 0


def redis_concurrence_test(thread_id):
    redis_nodes = [ {"host":"172.18.0.11","port":8888},
                    {"host":"172.18.0.12","port":8888},
                    {"host":"172.18.0.13","port":8888},
                    {"host":"172.18.0.14","port":8888},
                    {"host":"172.18.0.15","port":8888},
                    {"host":"172.18.0.16","port":8888}]
    try:
        redis_conn = StrictRedisCluster(startup_nodes=redis_nodes, password="******")
    except Exception:
        raise Exception
    redis_conn.config_set("cluster-require-full-coverage", "yes")
    counter = 0
    for i in range(0, 10000):
        counter = counter + 1
        redis_conn.set("key_" + str(thread_id)+"_"+str(counter), "value_" + str(i))
        #redis_conn.execute_command("wait", 1, 0)
        if counter == 1000:
            print(str(thread_id)+":insert 1000 keys " + str(str(datetime.datetime.now())))
            counter = 0



if __name__ == "__main__":
    #redis_cluster_write()
    threads = []
    for i in range(10):
        t = threading.Thread(target=redis_concurrence_test, args=(i,))
        threads.append(t)
    begin_time = ctime()
    for t in threads:
        t.setDaemon(True)
        t.start()
    for t in threads:
        t.join()

代码100分

https://redis.io/commands/wait

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/10274.html

(0)
上一篇 2022-12-30 14:00
下一篇 2022-12-30 15:00

相关推荐

  • 并发事务问题与事务隔离级别[通俗易懂]

    并发事务问题与事务隔离级别[通俗易懂]1.并发事务问题 1)脏读:一个事物读到另一个事务还没有提交的数据。 2)不可重复读:一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。 3)幻读:一个事务按照条件查询数据时,没有对

    2023-05-11
    118
  • 如何使用Python的read函数

    如何使用Python的read函数Python是一种高级编程语言,非常受欢迎,因为它非常易学、易用。在Python中,read函数是一个非常有用的内置函数。在文件处理方面,该函数可以读取文本文件中的内容,并将其存储在变量中。在今天的文章中,我将介绍如何使用Python的read函数。

    2024-07-23
    6
  • Mongodb聚合查询_mongodb查询指定字段

    Mongodb聚合查询_mongodb查询指定字段https://www.cnblogs.com/zhoujie/p/mongo1.html mongodb高级聚合查询 在工作中会经常遇到一些mongodb的聚合操作,特此总结下。mongo存储的可以

    2023-02-13
    118
  • Python中的实数和浮点数:区别和应用

    Python中的实数和浮点数:区别和应用在数学中,实数是指包括正数、负数和0在内的所有实数,它们可以通过一个无限不循环的十进制小数来表示。而浮点数则是指带有小数点或指数的数,包括单精度浮点数和双精度浮点数。在Python中,实数可以使用int和long类型来表示,而浮点数则使用float或complex类型。

    2024-01-05
    91
  • 文件名中无效目录名是什么?

    文件名中无效目录名是什么?在处理文件时,可能会遇到无效目录名的情况。这个问题是什么意思?为什么会出现这个问题?解决这个问题有没有什么技巧?在本文中,我们将探讨这些问题并提供一些解决方案。

    2024-05-18
    51
  • 使用Power BI构建数据仓库与BI方案[通俗易懂]

    使用Power BI构建数据仓库与BI方案[通俗易懂]杀手级特性 今年Power BI的几大杀手级特性的GA,可以让其构建完整的数据仓库/数据湖和BI分析一站式方案。 Power BI Premium Per User-超低的价格 Large datas

    2023-04-14
    134
  • Python List:高效处理序列数据

    Python List:高效处理序列数据List是Python的一种基本数据类型,它是一个有序序列,可以包含任意类型的数据,同时可以动态添加和删除元素。以下是一些List的基本操作:

    2024-03-07
    60
  • Oracle学习笔记二十八:视图的使用「建议收藏」

    Oracle学习笔记二十八:视图的使用「建议收藏」一、视图概念 • 视图概念 • 视图是基于一个表或多个表或视图的逻辑表(虚表),本身不包含数据,通过它可以对表里面的数据进行查询。 • 基表 • 视图是从一个或多个实际表中获得的,这些表的数据存放在数

    2023-05-23
    120

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注