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 · 4470 次点击
    这是一个创建于 1899 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我当前是使用 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
    @alexzhu592
    @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   ·   实用小工具   ·   2429 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 16:06 · PVG 00:06 · LAX 08:06 · JFK 11:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.