redis 并发下写入数据丢失 - V2EX
请不要在回答技术问题时复制粘贴 AI 生成的内容
shuangdeyu

redis 并发下写入数据丢失

  •  
  •   shuangdeyu Aug 31, 2020 4410 views
    This topic created in 2086 days ago, the information mentioned may be changed or developed.

    不懂就问,使用 redis 的 list 类型做消息队列,通过这个队列将要写到 mysql 的数据延后批量写入

    遇到的问题是,使用 jmeter 测并发的时候发现,10000 线程的时候,写到 redis 的数据会丢失,而且丢失数量是不规则的; 5000 线程以内则一切正常,主要想知道这是什么原因?单机如何去优化?替代方案比如 MQ 暂时不考虑。

    使用语言是 Go,代码如下,其实也很简单,只是往 redis 队列中推入数据,用 Redis Manager 观察:

    func Testt(c *gin.Context) { // 这是测试数据,数据长度小得到的也是一样的结果 //x := `{"Dateline":"2020-08-31 13:34:59","Error":200002,"Id":"ee0da19f-eb05-4728-8e23-107336043ede","Ip":"192.168.2.150","Method":"POST","Resp":"null"}` // 这是封装的 LPush 函数 dbhelper.Lpush("testttt", "_api", "1") c.JSON(200, gin.H{ "e": 0, "msg": "success", }) } 

    10000 线程的测试结果,只存进去 1542 个数据:

    5000 线程的测试结果,5000 个数据全部写进队列了:

    Supplement 1    Sep 1, 2020

    感谢大家的回答,问题找到了,测试代码没有严谨对待,没有抛出错误信息,饶了弯路 =_= ,一直在钻redis配置的牛角尖,加上后抛出的错误是"connection pool timeout",然后修改代码,在建立连接客户端的时候在"redis.Options"中配置连接池大小等属性后问题解决,因为默认的"PoolSize"只有10,一个进程内10000的并发量自然是不够用了。

    配置连接数上也发现了问题,修改"redis.conf"连接数后发现数量怎么都不会增加,因为前有解决mysql连接数问题的经验,很快就找到还有一个隐藏的"limit.conf"中一个"LimitNOFILE"参数限制了最大连接数,修改后连接数修改就能生效了。

    12 replies    2020-09-01 10:01:05 +08:00
    useben
        1
    useben  
       Aug 31, 2020
    查看下 redis 连接是否有错误, 调大连接数
    saturn7
        2
    saturn7  
       Aug 31, 2020
    看 demo 代码象只是复用单实例连接到 Redis Server,典型的写 PHP 思维。解决要用连接池 + 并发锁。
    micean
        3
    micean  
       Aug 31, 2020
    lpush 的结果不观察一下吗?
    JJstyle
        4
    JJstyle  
       Aug 31, 2020
    @saturn7 楼主需要能并发插入数据,你给加一个并发锁,是要解决什么问题?
    fanpei0121
        5
    fanpei0121  
       Aug 31, 2020
    经测试 并发 10 万条 redis 插入,没有漏数据,测试代码不要太在意细节。


    func Test(c *gin.Context) {
    // 这是测试数据,数据长度小得到的也是一样的结果
    x := `{"Dateline":"2020-08-31 13:34:59","Error":200002,"Id":"ee0da19f-eb05-4728-8e23-107336043ede","Ip":"192.168.2.150","Method":"POST","Resp":"null"}`

    // 这是封装的 LPush 函数
    rdb := redis.NewClient(&redis.Options{
    Addr: "localhost:6379",
    Password: "",
    DB: 0,
    })
    dataChan := make(chan string, 1000)

    go func() {
    for i := 1; i <= 100000; i++ {
    dataChan <- x
    }
    }()

    for j := 1; j < 20; j++ {
    go func() {
    for {
    data := <-dataChan
    err := rdb.RPush("test111", data).Err()
    logs.Error(err)
    }
    }()
    }

    c.JSON(200, gin.H{
    "e": 0,
    "msg": "success",
    })
    }
    huntcool001
        6
    huntcool001  
       Aug 31, 2020
    没看明白. 你是怎么知道 lpush 结果正常的.. redis 返回值是什么, 异常有 catch 住打印没?


    另外,消息队列最好用 Redis Stream 来做.
    Citrus
        7
    Citrus  
       Aug 31, 2020 via iPhone
    你写请求发出去就不管了是咋知道这成功了呢?
    90928yao
        8
    90928yao  
       Aug 31, 2020
    打个 redis 返回啊。肯定很多报错 拿不到链接
    th00000
        9
    th00000  
       Aug 31, 2020
    猜测一下: Redis 的写入是单线程的, 假设你的 dbhelper 是有缓存的, 每次去写的时候会等待前面写入之后再去写
    但是你并发比较高, 导致前面的这个 dbhelper 还没来得及写入, 就被拎出来又存了数据, 继续排队, 导致只有最终数据写进去了
    ZehaiZhang
        10
    ZehaiZhang  
       Aug 31, 2020
    之前 trycatch 发现了一些因为数据格式问题导致的 push 失败
    PiersSoCool
        11
    PiersSoCool  
       Aug 31, 2020
    大哥你这用异步跑,又没有同步措施,协程没跑完,主进程就退出了,肯定有问题啊
    securityCoding
        12
    securityCoding  
       Sep 1, 2020
    @PiersSoCool 加个 waitGroup 或者 chan
    About     Help     Advertise     Blog     API     FAQ     Solana     2541 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 70ms UTC 15:24 PVG 23:24 LAX 08:24 JFK 11:24
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86