iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >基于redis乐观锁怎么实现并发排队
  • 610
分享到

基于redis乐观锁怎么实现并发排队

2023-07-04 20:07:00 610人浏览 薄情痞子
摘要

这篇“基于redis乐观锁怎么实现并发排队”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于Redis乐观锁怎么实现并发排队

这篇“基于redis乐观怎么实现并发排队”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于Redis乐观锁怎么实现并发排队”文章吧。

有个需求场景是这样的,使用redis控制scrapy运行的数量。当系统的后台设置为4时,只允许scapry启动4个任务,多余的任务则进行排队。

概况

最近做了一个Django + scrapy + celery + redis 的爬虫系统,客户购买的主机除了跑其他程序外,还要跑我开发的这套程序,所以需要手动控制scrapy的实例数量,避免过多的爬虫给系统造成负担。

流程设计

爬虫任务由用户以请求的方式发起,所有的用户的请求统一进入到celery进行排队;
2、任务数量控制的执行就交给reids,经由celery保存到redis,包含了爬虫启动所需要的必要信息,从redis取一条信息即可启动一个爬虫;
3、通过scrapyd的接口来获取当前在运行的爬虫数量,以便决定下一步流程:如果小于4,则从redis中取相应数量的信息来启动爬虫,如果大于等于4,则继续等待;
4、如果在运行爬虫的数量有所减少,则及时从reids中取相应数量的信息来启动爬虫。

代码实现

业务代码有点复杂和啰嗦,此处使用伪代码来演示

import redis# 实例化一个redis连接池pool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True, db=4, passWord='')r = redis.Redis(connection_pool=pool)# 爬虫实例限制为4 即只允许4个scrapy实例在运行limited = 4# 声明redis的乐观锁lock = r.Lock()# lock.acquire中有while循环,即它会线程阻塞,直到当前线程获得redis的lock,才会继续往下执行代码if lock.acquire():# 1、从reids中取一条爬虫信息info = redis.get() # 2、while循环监听爬虫运行的数量while True:req = requests.get('Http://127.0.0.1:6800/daemonstatus.JSON').json()# 统计当前有多少个爬虫在运行running = req.get('running') + req.get('pending')# 3、判断是否等待还是要增加爬虫数量# 3.1 如果在运行的数量大于等于设置到量 则继续等待if running >= limited:continue# 3.2 如果小于 则启动爬虫start_scrapy(info)# 3.3 将info从redis中删除redis.delete(info)# 3.4 释放锁lock.release()break

当前,这只是伪代码而已,实际的业务逻辑可能是非常复杂的,如:

@shared_taskdef scrapy_control(key_uuid):    r = redis.Redis(connection_pool=pool)    db = MysqlDB()    speed_limited = db.fetch_config('REPTILE_SPEED')    speed_limited = int(speed_limited[0])    keywords_num = MysqlDB().fetch_config('SEARCH_RANDOM')    keywords_num = int(keywords_num[0])    # while True:    lock = r.lock('lock')    with open('log/celery/info.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + ' 进入处理环节' +  '\n')    try:        # acquire默认阻塞 如果获取不到锁时 会一直阻塞在这个函数的while循环中        if lock.acquire():            with open('log/celery/info.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + ' 获得锁' +  '\n')            # 1 从redis中获取信息            redis_obj = json.loads(r.get(key_uuid))            user_id = redis_obj.get('user_id')            contents = redis_obj.get('contents')                        # 2 使用while循环处理核心逻辑                      is_hold_print = True            while True:                req = requests.get('http://127.0.0.1:6800/daemonstatus.json').json()                running = req.get('running') + req.get('pending')                # 3 如果仍然有足够的爬虫在运行 则hold住redis锁,等待有空余的爬虫位置让出                if running >= speed_limited:                    if is_hold_print:                        with open('log/celery/info.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + ' 爬虫在运行,线程等待中' +  '\n')                        is_hold_print = False                    time.sleep(1)                    continue                                # 4 有空余的爬虫位置 则往下走                # 4.1 处理完所有的内容后 释放锁                if len(contents) == 0:                    r.delete(key_uuid)                    with open('log/celery/info.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + ' 任务已完成,从redis中删除' +  '\n')                    lock.release()                    with open('log/celery/info.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + ' 释放锁' +  '\n')                    break                # 4.2 创建task任务                task_uuid = str(uuid.uuid4())                article_obj = contents.pop()                article_id = article_obj.get('article_id')                article = article_obj.get('content')                try:                    Task.objects.create(                        task_uuid = task_uuid,                        user_id = user_id,                        article_id = article_id,                        content = article                    )                except Exception as e:                    with open('log/celery/error.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + '->' + str(task_uuid) + ' 创建Task出错: ' + str(e) +  '\n')                # finally:                # 4.3 启动爬虫任务 即便创建task失败也会启动                try:                    task_chain(user_id, article, task_uuid, keywords_num)                except Exception as e:                    with open('log/celery/error.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + ' 启动任务链失败: ' + str(e) +  '\n')                                # 加入sleep 防止代码执行速度快于爬虫启动速度而导致当前线程启动额外的爬虫                time.sleep(5)    except Exception as e:        with open('log/celery/error.log', 'a') as f: f.write(str(datetime.datetime.now()) + '--' + str(key_uuid) + ' 获得锁之后的操作出错: ' + str(e) +  '\n')        lock.release()

小坑
scrapy启动速度相对较慢,所以while循环中,代码中执行到了爬虫的启动,需要sleep一下再去通过scrapyd接口获取爬虫运行的数量,如果立刻读取,可能会造成误判。

以上就是关于“基于redis乐观锁怎么实现并发排队”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网精选频道。

--结束END--

本文标题: 基于redis乐观锁怎么实现并发排队

本文链接: https://www.lsjlt.com/news/347431.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 基于redis乐观锁实现并发排队
    有个需求场景是这样的,使用Redis控制scrapy运行的数量。当系统的后台设置为4时,只允许scapry启动4个任务,多余的任务则进行排队。 概况 最近做了一个django + scrapy + celery + re...
    99+
    2022-12-25
    redis队列实现高并发 redis消息队列实现高并发 redis乐观锁实现高并发
  • 基于redis乐观锁怎么实现并发排队
    这篇“基于redis乐观锁怎么实现并发排队”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“基于redis乐观锁怎么实现并发排队...
    99+
    2023-07-04
  • MyBatis中怎么实现乐观锁
    在MyBatis中实现乐观锁可以通过在对应的实体类中添加一个版本号字段,并在对应的更新操作中更新这个版本号字段。具体步骤如下: 在...
    99+
    2024-03-07
    MyBatis
  • 悲观锁与乐观锁怎么利用Hibernate实现
    这篇文章将为大家详细讲解有关悲观锁与乐观锁怎么利用Hibernate实现,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。四种隔离机制不要忘记:(1,2,4,8)1.read-uncommitt...
    99+
    2023-05-31
    hibernate 悲观锁 乐观锁
  • redis怎么实现并发锁
    Redis可以使用SETNX(SET if Not eXists)命令实现并发锁。以下是一个使用Redis实现并发锁的示例代码:``...
    99+
    2023-08-30
    redis
  • Redis怎么加锁实现高并发
    在Redis中可以使用SETNX命令实现简单的分布式锁。SETNX命令是一个原子操作,用于设置一个键的值,如果该键不存在,则设置成功...
    99+
    2023-08-31
    Redis
  • JAVA怎么实现乐观锁及CAS机制
    本篇内容介绍了“JAVA怎么实现乐观锁及CAS机制”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言生活中我们看待一个事物总有不同的态度,比...
    99+
    2023-07-04
  • 【MySQl】MySQl中的乐观锁是怎么实现的
    文章目录 前言一、乐观锁二、如何实现乐观锁呢,一般来说有以下2种方式2.1、使用数据版本(Version)记录机制实现2.2、乐观锁定的第二种实现方式和第一种差不多 前言 mysql中...
    99+
    2023-09-20
    mysql oracle 数据库
  • 怎么使用MyBatisPlus+SpringBoot实现乐观锁功能
    今天小编给大家分享一下怎么使用MyBatisPlus+SpringBoot实现乐观锁功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了...
    99+
    2023-07-05
  • 基于Redis缓存怎么实现分布式锁
    本篇内容介绍了“基于Redis缓存怎么实现分布式锁”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是分布式锁首先我们先来简单了解一下什么是...
    99+
    2023-06-19
  • redis怎么实现并列排序
    Redis可以通过有序集合(Sorted Set)来实现并列排序。有序集合是一种特殊的数据结构,其中的每个成员都关联着一个分数(sc...
    99+
    2023-09-06
    redis
  • redis队列实现高并发的方法是什么
    在Redis中实现高并发的队列,可以使用Redis的list数据结构来实现队列的功能。具体步骤如下: 使用LPUSH命令将数据推...
    99+
    2024-04-09
    redis
  • 基于JS怎么实现消消乐游戏
    这篇文章主要讲解了“基于JS怎么实现消消乐游戏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于JS怎么实现消消乐游戏”吧!游戏的准备工作首先我们思考游戏的机制: 游戏有一个“棋盘”,是一个...
    99+
    2023-06-30
  • 基于Python怎么实现音乐播放器
    本篇内容主要讲解“基于Python怎么实现音乐播放器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“基于Python怎么实现音乐播放器”吧!一、环境设置第一步引入必须的各类包import ...
    99+
    2023-06-30
  • JAVA多线程怎么实现用户任务排队并预估排队时长
    这篇文章主要介绍“JAVA多线程怎么实现用户任务排队并预估排队时长”,在日常操作中,相信很多人在JAVA多线程怎么实现用户任务排队并预估排队时长问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JAVA多线程怎么...
    99+
    2023-06-22
  • 基于Zookeeper怎么实现分布式锁
    这篇文章主要介绍“基于Zookeeper怎么实现分布式锁”,在日常操作中,相信很多人在基于Zookeeper怎么实现分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”基于Zookeeper怎么实现分布式锁...
    99+
    2023-06-22
  • php队列处理高并发怎么实现
    在PHP中实现高并发的队列处理可以考虑以下几种方式: 使用消息队列:可以使用开源的消息队列系统,如RabbitMQ、Kafka等...
    99+
    2023-10-28
    php
  • golang并发安全及锁怎么实现
    本文小编为大家详细介绍“golang并发安全及锁怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“golang并发安全及锁怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。并发安全和锁有时候在Go代码中...
    99+
    2023-06-30
  • 基于Java怎么实现Redis多级缓存
    这篇文章主要介绍“基于Java怎么实现Redis多级缓存”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于Java怎么实现Redis多级缓存”文章能帮助大家解决问题。一、多级缓存1. 传统缓存方案请...
    99+
    2023-06-29
  • 基于jQuery排序及怎么实现Tab栏特效
    今天小编给大家分享一下基于jQuery排序及怎么实现Tab栏特效的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、jQuer...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作