长期支持版本

    社区创新版本

      Gazelle加速redis

      背景介绍

      Gazelle是一款高性能用户态协议栈。它基于DPDK在用户态直接读写网卡报文,共享大页内存传递报文,使用轻量级LwIP协议栈。能够大幅提高应用的网络I/O吞吐能力。专注于数据库网络性能加速,如MySQL、redis等。

      Gazelle相比于内核协议栈在redis测试中有明显的提升,以arm架构、8u32g规格、ovs+dpdk虚拟机的set和get测试为例,测是结果如下,set提升约1.7倍,get提升约1.5倍,其中测试连接数为1k,包长为默认包长3。

      #kernel
      redis-benchmark -h 192.168.1.127 -p 6379 -c 1000 -n 10000000 -r 10000000 -t set,get --threads 12
      #set
      Summary:
        throughput summary: 132402.98 requests per second
        latency summary (msec):
                avg       min       p50       p95       p99       max
              7.474     1.376     7.207     9.399    14.255    30.879
      #get
      Summary:
        throughput summary: 142834.69 requests per second
        latency summary (msec):
                avg       min       p50       p95       p99       max
              6.919     1.384     6.663     8.751    13.311    24.207
      
      #gazelle
      redis-benchmark -h 192.168.1.127 -p 6379 -c 1000 -n 10000000 -r 10000000 -t set,get --threads 12
      #set
      Summary:
        throughput summary: 359389.03 requests per second
        latency summary (msec):
                avg       min       p50       p95       p99       max
              2.736     0.240     2.735     2.895     3.127     9.471
      #get
      Summary:
        throughput summary: 359401.97 requests per second
        latency summary (msec):
                avg       min       p50       p95       p99       max
              2.752     0.488     2.751     2.903     3.135    16.671
      

      说明: 不同的硬件配置及组网环境会影响性能提升的效果,上述测试结果仅供参考。

      功能约束

      • 当前仅支持IPV4,IPV6暂不支持
      • 并发数限制最大为2w
      • 当前不支持gazelle多进程,即一个节点上不能用gazelle启动多个redis server
      • redis主从集群中,内核态日志反复打印主从重连日志,用户态只打印一次,此为正常现象,无功能影响。原因:一个内核态主节点下线后,表现为从节点尝试连接主节点,发送SYN报文,主节点处于TIME_WAIT状态回复RST报文关闭连接,以此反复。一个用户态主节点下线后,由于gazelle+redis退出后连接完全关闭,未处于TIME_WAIT状态,从节点尝试连接主节点,发送SYN报文,主节点不会回复RST报文,所以gazellectl lstack show ip -c查询时,会存在一个处于SYN_SENT状态的连接。

      Gazelle加速redis测试步骤

      环境要求

      硬件

      单机测试需要服务端(Server)、客户端(Client)各一台;
      主从模式测试至少两台服务端(一主一从)、一台客户端;
      哨兵模式测试至少两台redis服务端(一主一从)、两台哨兵服务端、一台客户端;
      集群模式测试至少六台redis服务端(三主三从)、一台客户端。

      软件

      redis软件包下载,本次使用版本为redis-6.2.9。

      Server端部署

      关闭测试影响项

      #关闭防火墙
      systemctl stop iptables
      systemctl stop firewalld
      

      编译安装redis

      tar zxvf redis-6.2.9.tar.gz 
      cd redis-6.2.9/
      make clean
      make -j 32
      make install
      

      gazelle运行环境部署

      • 安装gazelle及依赖
      yum -y install gazelle dpdk libconfig numactl libboundscheck libcap 
      
      • 修改/etc/gazelle/lstack.conf配置文件中参数如下,其他配置参数可保持默认值。
      配置项描述
      dpdk_args["--socket-mem", "2400,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary"]配置cpu和网卡所在的numa使用2400M内存(可根据并发数减少);如果cpu和网卡不在一个numa上,则对应numa都需要配置内存;如果是mlx网卡,需要追加配置"-d", "librte_net_mlx5.so"
      num_cpus"2"选择一个cpu绑定lstack
      mbuf_count_per_conn34每个连接需要的mbuf数量
      tcp_conn_count20000redis测试最大并发数
      #服务端分配大页
      mkdir -p /mnt/hugepages-lstack
      chmod -R 700 /mnt/hugepages-lstack
      mount -t hugetlbfs nodev /mnt/hugepages-lstack -o pagesize=2M #不能重复操作,否则大页被占用不能释放
      echo 2048 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages #根据实际选择pagesize
      cat /sys/devices/system/node/node0/hugepages/hugepages-2048kB/free_hugepages #查询对应node上实际可用的大页内存
      
      #服务端加载ko(mlx网卡可跳过此步骤)
      modprobe vfio enable_unsafe_noiommu_mode=1
      modprobe vfio-pci
      
      #服务端绑定网卡到用户态(mlx网卡可跳过此步骤)
      ip link set enp4s0 down
      dpdk-devbind -b vfio-pci enp4s0
      
      #gazelle部署完成,待app部署
      

      说明:
      Gazelle部署详见Gazelle用户指南
      不同网卡绑定用户态方法详见Gazelle网卡支持及使用

      redis服务端部署

      redis环境部署包括单机部署、主从模式部署、哨兵模式部署和集群模式部署,所有场景的redis server的redis.conf文件,均需要做如下配置:

      #关闭保护模式
      protected-mode no
      #gazelle暂不支持此参数进行后台运行
      daemonize no
      #开启AOF持久化,redis单机测试可不配置
      appendonly yes
      
      redis单机部署

      redis单机测试包含一台server,部署好gazelle和redis后,可以直接启动gazelle+redis服务

      LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server /root/redis-6.2.9/redis.conf
      
      redis主从模式部署

      主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。redis主从模式包括至少两台server,配置方法有两种:

      主从配置方式1
      从节点redis.conf配置文件中添加如下配置,然后分别启动redis主从节点

      #192.168.1.127 6379为主节点服务的ip和port
      slaveof 192.168.1.127 6379
      
      LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server /root/redis-6.2.9/redis.conf
      

      主从配置方式2
      完成主从节点通用配置修改后,启动redis主从节点(此时还没有建立主从关系),在客户端执行以下命令

      redis-cli -h 192.168.1.127 slaveof NO ONE #主节点
      redis-cli -h 192.168.1.128 slaveof 192.168.1.127 6379 #从节点
      

      主从信息查询

      [root@openEuler redis-6.2.9]# redis-cli -h 192.168.1.127 info Replication
      # Replication
      role:master
      connected_slaves:1
      slave0:ip=192.168.1.128,port=6379,state=online,offset=780,lag=0
      ......
      
      [root@openEuler redis-6.2.9]# redis-cli -h 192.168.1.128 info Replication
      # Replication
      role:slave
      master_host:192.168.1.127
      master_port:6379
      master_link_status:up
      ......
      
      redis哨兵模式部署

      哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障。主从切换技术的方法是:当服务器宕机后,需要手动一台从机切换为主机,这需要人工干预,不仅费时费力而且还会造成一段时间内服务不可用。为了解决主从复制的缺点,就有了哨兵机制。redis哨兵模式测试至少需要两台redis服务端和两台哨兵服务端。

      • 按照主从模式部署方法将两台redis服务端启动
      • 在两台哨兵服务端安装部署redis,分别修改sentinel.conf配置文件
      protected-mode no #关闭保护模式
      daemonize yes #后台运行,日志记录在logfile
      logfile "/var/log/sentinel.log" #指定日志存放路径
      sentinel monitor mymaster 192.168.1.127 6379 1 #该主节点的名称是mymaster,监控master的ip、端口,1是至少需要1个哨兵节点同意,才能判定主节点故障并进行故障转移
      sentinel down-after-milliseconds mymaster 30000 #判断服务器down掉的时间周期,默认30000毫秒(30秒)
      sentinel failover-timeout mymaster 50000 #故障节点的最大超时时间为50000
      
      • 启动哨兵(内核态启动),查询哨兵信息
      [root@openEuler redis-6.2.9]#redis-sentinel sentinel.conf
      [root@openEuler redis-6.2.9]#ps -ef|grep redis-sentinel 
      root       5961      1  0 13:36 ?        00:00:00 redis-sentinel *:26379 [sentinel]
      [root@openEuler redis-6.2.9]#redis-cli -p 26379 info sentinel
      # Sentinel
      sentinel_masters:1
      sentinel_tilt:0
      sentinel_running_scripts:0
      sentinel_scripts_queue_length:0
      sentinel_simulate_failure_flags:0
      master0:name=mymaster,status=ok,address=192.168.1.127:6379,slaves=2,sentinels=3
      

      说明:
      redis server和redis 哨兵不可以在同一个节点上,否则无法正常主备切换;
      redis 哨兵暂不支持用户态启动。

      redis集群模式部署

      单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,其作用是提供在多个Redis节点间共享数据的程序集。redis集群测试至少需要六台redis服务端。

      • 在六台redis服务端安装部署redis,分别修改redis.conf配置文件
      protected-mode no #关闭保护模式
      daemonize no #前台运行
      bind 0.0.0.0
      port 6379 #redis部署在不同的虚机上,ip不一样,端口可以保持默认
      appendonly yes #开启aof持久化
      cluster-enabled yes #开启集群模式
      cluster-config-file nodes.conf #集群模式的配置文件名称,无需手动创建,由集群自动维护
      cluster-node-timeout 5000 #集群中节点之间心跳超时时间
      
      • 分别启动六台redis服务端
      LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server /root/redis-6.2.9/redis.conf
      
      • 在客户端执行命令创建集群,同意集群中master与slave节点的分配情况
      [root@openEuler redis-6.2.9]#redis-cli --cluster create --cluster-replicas 1 192.168.1.127:6379 192.168.1.128:6379 192.168.1.129:6379 192.168.1.130:6379 192.168.1.131:6379 192.168.1.132:6379
      >>> Performing hash slots allocation on 6 nodes...
      ......
      Can I set the above configuration? (type 'yes' to accept): yes
      >>> Nodes configuration updated
      >>> Assign a different config epoch to each node
      >>> Sending CLUSTER MEET messages to join the cluster
      Waiting for the cluster to join
      ...
      >>> Performing Cluster Check (using node 192.168.1.127:6379)
      ......
      [OK] All nodes agree about slots configuration.
      >>> Check for open slots...
      >>> Check slots coverage...
      [OK] All 16384 slots covered. #hash slots分配OK则集群创建成功
      
      #redis-cli --cluster:代表集群操作命令;create:代表是创建集群;--cluster-replicas 1 :指定集群中每个master的副本个数为1
      #此时节点总数 ÷ (replicas + 1) 得到的就是master的数量n。因此节点列表中的前n个节点就是master,其它节点都是slave节点,随机分配到不同master
      
      • 查询集群信息
        集群中任意一个正常运行的server都可以作为切入点
      #查看集群状态信息
      [root@openEuler redis-6.2.9]# redis-cli -h 192.168.1.127 cluster info
      cluster_state:ok #如果这里是fail,可以看下hash slots分配失败
      cluster_slots_assigned:16384
      cluster_slots_ok:16384
      cluster_slots_pfail:0
      cluster_slots_fail:0
      ......
      
      #查看集群的主从关系
      [root@openEuler redis-6.2.9]# redis-cli -h 192.168.1.128 cluster nodes
      514b35aaa5035d489b60a0e8f8fb01d1c20734ce 192.168.1.129:6379@16379 slave 50aa44a1e4a6a0c75cf2f9b20055bfaa77d1b163 0 1724919619916 1 connected
      50aa44a1e4a6a0c75cf2f9b20055bfaa77d1b163 192.168.1.127:6379@16379 master - 0 1724919617960 1 connected 0-5460
      a94402ca747ead08e4b93ff975dfbe995068ecbf 192.168.1.130:6379@16379 slave 0a569e1ac4e373a22abcbf6ce6b8118fba3d4d6e 0 1724919618000 3 connected
      8c4040a4fa8456044acad2518dc45b8236ba44c4 192.168.1.128:6379@16379 myself,slave 44a96161651c8383fb4966c6dde45d400fe2a203 0 1724919617000 2 connected
      0a569e1ac4e373a22abcbf6ce6b8118fba3d4d6e 192.168.1.132:6379@16379 master - 0 1724919618975 3 connected 10923-16383
      44a96161651c8383fb4966c6dde45d400fe2a203 192.168.1.131:6379@16379 master - 0 1724919619617 2 connected 5461-10922
      #可以看出127、131、132是master节点,128、129、130为slave节点,且可以通过slave后的node id找到其对应的master节点
      

      Client部署redis-benchmark工具

      • 编译安装

      redis-benchmark为redis自带的测试工具,与服务端一样编译安装redis即可。

      • 测试命令
      #单机、主从模式、哨兵模式
      #set,get
      redis-benchmark -h 192.168.1.127 -p 6379 -c 1000 -n 10000000 -d 3 -r 10000000 -t set,get --threads 12
      #其中,-h:指定redis服务端地址;-p:指定redis服务端端口;-c:指定客户端并发连接数;-n:指定请求总数;-t:指定测试命令;-d:指定数据包大小
      #主从模式和哨兵模式下,由于默认配置了slave-read-only yes,从节点redis只能执行get命令。
      
      #集群模式
      #set,get
      redis-benchmark -h 192.168.1.127 -p 6379 -c 1000 -n 10000000 -d 3 -r 10000000 -t set,get --threads 12 --cluster
      #-h只需指定集群中任意一个可用节点即可
      

      Gazelle加速redis成功日志样例

      [root@openEuler redis-6.2.9]# LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server redis.conf
      LSTACK[2555459]: LD_PRELOAD ok
      dpdk argv: --socket-mem 2400,0,0,0 --huge-dir /mnt/hugepages-lstack --proc-type primary
      LSTACK[2555459]: cfg_init success
      #dpdk启动log省略,环境不同存在差异
      ......
      #gazelle打印init success则启动成功
      LSTACK: gazelle_stack_thread:533 stack_00 init success
      LSTACK: gazelle_network_init:328 gazelle_network_init success
      #redis启动log省略,与内核态redis启动log相同
      

      启动成功后,可以在客户端ping lstack.conf中配置的用户态ip,ping通则gazelle加速redis部署成功。

      文档捉虫

      “有虫”文档片段

      问题描述

      提交类型 issue

      有点复杂...

      找人问问吧。

      PR

      小问题,全程线上修改...

      一键搞定!

      问题类型
      规范和低错类

      ● 错别字或拼写错误;标点符号使用错误;

      ● 链接错误、空单元格、格式错误;

      ● 英文中包含中文字符;

      ● 界面和描述不一致,但不影响操作;

      ● 表述不通顺,但不影响理解;

      ● 版本号不匹配:如软件包名称、界面版本号;

      易用性

      ● 关键步骤错误或缺失,无法指导用户完成任务;

      ● 缺少必要的前提条件、注意事项等;

      ● 图形、表格、文字等晦涩难懂;

      ● 逻辑不清晰,该分类、分项、分步骤的没有给出;

      正确性

      ● 技术原理、功能、规格等描述和软件不一致,存在错误;

      ● 原理图、架构图等存在错误;

      ● 命令、命令参数等错误;

      ● 代码片段错误;

      ● 命令无法完成对应功能;

      ● 界面错误,无法指导操作;

      风险提示

      ● 对重要数据或系统存在风险的操作,缺少安全提示;

      内容合规

      ● 违反法律法规,涉及政治、领土主权等敏感词;

      ● 内容侵权;

      您对文档的总体满意度

      非常不满意
      非常满意
      提交
      根据您的反馈,会自动生成issue模板。您只需点击按钮,创建issue即可。
      文档捉虫
      编组 3备份