【经验分享】在DragonOS中运行Redis

个人环境

  • 操作系统:Ubuntu22.04 LTS
  • gcc版本:11.4.0
  • musl版本:1.2.2

编译Redis

使用脚本自动编译

  1. 安装linux-headers

    sudo apt install linux-headers-$(uname -r)

  2. 下载Makefile
    Makefile.md (2.1 KB)

  3. 命令行输入

    make
    

    即可自动下载源码编译

  4. 将编译后的redis-server、redis.conf文件拷贝到DragonOS目录的bin/sysroot/bin

编译时出现的问题

  1. Redis版本为5.0.7及更低版本,可能出现编译错误:multiple definition of SDS_NOINIT’`

    解决方法:更换Redis版本

  2. Redis版本为**6.2.0并启用了MALLOC=libc,**可能出现编译错误:


    解决方法:1. 更换Redis版本 2. 取消MALLOC=libc 3. 修改源代码,见:https://github.com/redis/redis/issues/8530#issuecomment-784899849

运行

步骤

  1. 启动DragonOS,进入/bin目录

  2. 输入命令

    redis-server redis.conf
    
  3. 出现启动画面并且不报错说明成功启动

  4. 本地运行命令

    redis-cli -h 127.0.0.1 -p 12580
    

    出现前缀说明连接成功
    image

运行时出现的问题

  1. Redis使用listen系统调用时默认设置backlog参数为511,超出目前内核承载上限,会触发panic,并且错误信息无法正常打印,会卡在第一行
    image

    需要修改函数即可打印信息


    可以看见是内核分配器触发panic,大概率是内存溢出,因此需要在redis.conf将tcp-backlog设置为420以下

  2. 如果编译时未将源码中的MAX_ACCEPTS_PER_CALL的值修改为1,会导致连接redis时阻塞,具体步骤:

    1. 将源代码或Makefile中的MAX_ACCEPTS_PER_CALL修改为2

    2. 启动DragonOS,运行redis-server

    3. 本地开启两个终端,其中一个连接redis,会发现阻塞:

    4. 另一个连接redis,发现两个终端同时连接上

    猜测是因为Redis接收连接是采用非阻塞accept方法(使用fcntl将socket设置为O_NONBLOCK),而目前DragonOS无法将socket设置为非阻塞,因此当连接数少于MAX_ACCEPTS_PER_CALL的值时连接会被阻塞,直到连接数达到数量为止

可能的优化方向

  1. 优化内存管理模块和listen系统调用,支持更大的backlog
  2. 实现非阻塞的accept调用,避免多连接的阻塞
4 个赞

正在尝试运行redis,出现启动画面后就卡住了,没有panic或者别的信息打印出来,按照帖子修改了panic的打印信息也不起作用,请问有遇到过这个问题吗

  • gcc版本:gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
  • rustc版本:rustc 1.82.0-nightly (2cbbe8b8b 2024-07-28)
  • dragonos版本:a1fc824fcc3bd4c2e267d8c0e9e3866fc7310bba

不过在本地可以连接成功,dragonos也会在连接成功后打印更多信息。所以其实是redis进程占用了这个终端的原因()

摸鱼对当前主线运行的redis进行了简单的压力测试,给后续的qps优化目标做些参考。redis-benchmark是redis自带的压测工具,还有其他不同的命令类型,后续可以考虑根据我们的需求写一个自动化压测脚本

1 个赞

笑死,去年我测的qps好像是3。

似乎目前主线没办法指定 redis.conf 了,会显示无法打开配置文件,需要手动设置参数

检查一下文件是否存在?手动cat一下看看?

编译前将 redis.conf 拷贝到 /home 下,启动后cd过去再 redis-server redis.conf 就行了。

目前 网络重构分支 因 IPv6没实现 所以跑不了

重构之前也不支持ipv6吧?感觉ipv6不是主要原因?

确实不关v6的事。重构网络支线 现在Redis能进入listening,但是压测不返回。需要等Redis能够跑起来再合并支线吗?

压测不返回是啥意思?

这个,支线测试还不能通过

直接通过redis client去连接,能跑吗?

不能跑。pingPONG都不行。一直在open返回ENOENT,不知道是什么东西,或许是异步IO的连接被释放掉了?再看看。


debug发现redis server在处理收包时会尝试访问proc下自己进程的stat,但这个文件的生成貌似现在不支持?redis server的不断轮询访问该文件是目前server收包卡住的原因

1 个赞


在进行无数骚操作下(改redis-server源码、反复刷新(狗头,终于在本地收到dragonos redis server的pong。由此确定proc/{pid}/stat文件创建的和提升网络性能的需求

这性能怎么这么慢,比重构之前的慢很多