一个业务逻辑实现思路想问问大家 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
smallgoogle
V2EX    Python

一个业务逻辑实现思路想问问大家

  •  
  •   smallgoogle 2019-09-16 14:37:24 +08:00 4957 次点击
    这是一个创建于 2223 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我当前是使用 queue 单向队列;

    我需要实现功能如下:
    从数据库拉取数据,然后放入队列,然后多线程进行访问;
    线程每次使用 queue.get 获取一条数据访问;结束业务的时候又把数据 put 到队尾;
    一直循环;

    我另外还有一个线程,一直监听一个接收事件,如果接收到数据,就往队列里插入数据;
    那么问题来了,如果我想中间的时候往队列里增加数据 或者 删除数据怎么办? 比如我想删除队列里的某一个数据,好像 queue 不支持从中间删除数据。
    我这样的业务逻辑是不是不应该使用队列?

    第 1 条附言    2019-09-17 10:30:04 +08:00
    我的原始业务逻辑大概是:
    我想有一个数组 或者 队列 一样存放数据的地方,我不想每次都查询数据库,所以把数据拉出来就放在这里面,暂且称之为 [池] ;
    我要从池里拉取 url 进行访问,如果访问正常,则从新插到池最后,否则就丢弃,
    然后我是多线程的,我害怕线程会取到同一条数据,所以用了队列的方式,毕竟 queue.get 可以避免线程取到同一条数据;

    并且我有一个 redis 订阅,如果 redis 有新的数据了,我就把新的数据放入池里;

    其实最终我并不是想用队列来实现,只是害怕线程会取到同样的数据,我才用了队列;
    可是我发现队列并不能满足我的业务需求,比如往队列里删除指定数据;
    所以各位,有什么高见;
    27 条回复    2019-09-19 09:52:10 +08:00
    Amit
        1
    Amit  
       2019-09-16 14:44:40 +08:00
    这里没看出来哪里一定需要队列,queue.get 每次获取一条数据,数据还有插入删除的操作,不如直接使用数据库实现一个链表,定时任务每次查询一条头部记录
    smallgoogle
        2
    smallgoogle  
    OP
       2019-09-16 14:49:08 +08:00
    @Amit 因为不想每次都从数据库里拉数据,想第一次启动的时候就拉出数据放在队列,然后利用队列会锁住数据的功能,让多线程不会执行到同一条数据。
    speedofstephen
        3
    speedofstephen  
       2019-09-16 14:55:24 +08:00
    额 linkedlist 其实实现了 Queue
    xstoop
        4
    xstoop  
       2019-09-16 15:05:05 +08:00
    感觉你的队列使用有问题,一般队列的消费者跟生产者是分开的
    Lax
        5
    Lax  
       2019-09-16 15:07:08 +08:00
    “队列会锁住数据” ???这是个什么原理
    smallgoogle
        6
    smallgoogle  
    OP
       2019-09-16 15:07:37 +08:00
    @xstoop 我认为我使用队列是有问题的,但是应该使用啥,我就是不知道 = =
    smallgoogle
        7
    smallgoogle  
    OP
       2019-09-16 15:08:30 +08:00
    @Lax 我想表达的是,我多线程的时候,他们不会取到同一条数据的意思。 = =
    workspace
        8
    workspace  
       2019-09-16 16:17:38 +08:00
    关键字 redis list pop
    workspace
        9
    workspace  
       2019-09-16 16:20:16 +08:00
    另外可看下最近基于 redis 实现的一个简单队列: https://github.com/lgphone/delay-queue
    tt67wq
        10
    tt67wq  
       2019-09-16 16:43:48 +08:00
    redis zset 可以的,用分数来维持顺序
    xstoop
        11
    xstoop  
       2019-09-16 17:02:03 +08:00
    @smallgoogle 抛开你说的队列,线程这些。你大概描述一下你要实现的业务需求是什么呢
    raysonlu
        12
    raysonlu  
       2019-09-16 19:17:33 +08:00
    有点好奇你的业务,消费者每次消费完毕,都放回队列,然后又有一个生产者往队列塞东西,最后这个队列岂不是越滚越大? BTW,插队这种不恶劣行为估计是做不了的,删除的话,你可以再维护一个删除名单表让每次消费队列的时候都查询一下。zset 可以维持顺序,但消费者只能是定时任务中运行了。
    alexzhu592
        13
    alexzhu592  
       2019-09-16 19:25:09 +08:00 via Android
    @Lax 他应该是说的是阻塞
    alexzhu592
        14
    alexzhu592  
       2019-09-16 19:27:49 +08:00 via Android
    你的业务不适合用队列,想其他办法吧
    hspeed18
        15
    hspeed18  
       2019-09-17 02:10:19 +08:00   1
    为什么不说一下你的业务需求是什么,用队列的理由是什么?
    ziding
        16
    ziding  
       2019-09-17 09:21:27 +08:00
    感觉你是用错了,如果有任务优先级的要求,你应该用优先队列,而不是普通队列。如果用普通队列,要求能够撤回某些消息,应该用业务补偿,回滚的方式进行处理,而不是中间取消掉某个任务。
    hellotime
        17
    hellotime  
       2019-09-17 09:54:04 +08:00
    还是抛出原始需求比较好
    smallgoogle
        18
    smallgoogle  
    OP
       2019-09-17 10:31:24 +08:00
    @hspeed18
    @hellotime
    @alexzhu52
    @raysonlu
    @xstoop
    从看一下帖子不,我更了一下原始需求,给点高见;
    raysonlu
        19
    raysonlu  
       2019-09-17 10:45:37 +08:00
    像你说的,存放数据的地方,是个池或者数组,可以满足你增删需求,然后处理数据是个队列,可以满足多线程需求,那么,池归池,队列归队列,再找一个单线程的方法,让池中的数据迅速流入队列不就好了?
    hellotime
        20
    hellotime  
       2019-09-17 11:04:58 +08:00
    @smallgoogle 这哪是原始需求,你的原始需求应该类似是我想搞一个代理网站,逐个测试一下代理,如果代理不行了就遗弃,可以的就保存起来,待下次检测。原始需求指的是产品要啥功能,而不是你做为开发说你要个队列。。
    hellotime
        21
    hellotime  
       2019-09-17 11:07:33 +08:00
    多线程好像也取不到同一条记录把。
    lazyfighter
        22
    lazyfighter  
       2019-09-17 13:59:28 +08:00
    你应该说需求,另外这样使用队列,不会 oom 吗
    movax21h
        23
    movax21h  
       2019-09-17 17:09:02 +08:00
    应该不需要列队吧?
    因为你的多线程其实根本不会对同一个数据进行读写操作。(没有这个业务需求)

    简单点,如果有 4 个线程,把从数据库获取的 url,分成四份不就行了吗?
    最后处理完成之后,再合一起。

    不要打架,好处都有啥。
    Zzzz07
        24
    Zzzz07  
       2019-09-17 17:47:30 +08:00
    我也有个类似的需求,当有新的数据加入时就删除队列,出队时队列为空就重新去数据库中查询添加到队列中
    alexzhu592
        25
    alexzhu592  
       2019-09-17 22:19:19 +08:00
    其实你的需求就是要保证容器的并发安全,同时又增删操作,主要是查询,你就直接用 redis 就可以了
    jimrok
        26
    jimrok  
       2019-09-17 23:02:45 +08:00
    感觉是一个做爬虫的小白
    jiangbingo
        27
    jiangbingo  
       2019-09-19 09:52:10 +08:00
    K:V 映射的字典 pop 出 K-url,update V-数据 会有什么问题?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2837 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 02:42 PVG 10:42 LAX 19:42 JFK 22:42
    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