redis ConnectionResetError: [Errno 104] Connection reset by peer

链接空闲导致redis ConnectionResetError

在爬取京东商品评论时,开始我开启了redis_pipeline,所以没有出现redis connection reset问题,后来感觉没必要就关闭了redis_pipeline,就出现了redis ConnectionResetError: [Errno 104] Connection reset by peer,爬取一段时间后就会出现这个问题。

原因很好理解,一个商品如果有100页评论,每爬取一个商品sku才需要读取一次redis,所以有时候间隔很长,redis链接断开了。开始我设置了超时120和超时重试并且开启了health_check_interval,没有作用,看了下源码,发现有个socket_keepalive_options,开启试试吧。

#自定义的redis参数(连接超时之类的)
REDIS_PARAMS  = {    
    'socket_timeout': 10,
    'socket_connect_timeout': 10,
    'retry_on_timeout': True,
    'health_check_interval': 10,
    'socket_keepalive_options': True
    }

出现这种问题一般都是网络问题,或者自己代码不合理。

scrapy redis bloomfilter去重

scrapy redis bloomfilter去重

今天出现了两个错误,一是忘记了scrapyd重启后重置Open file limit,导致京东爬虫刷完了所有start_urls而没有获取什么数据;二是redis内存爆了,设置了3G最大内存,结果因为自己对redis的利用不够优化内存超限爬虫失败。

第一个问题可以写个自动化脚本定期reset,第二个问题的解决办法可以用bloomfilter代替scrapy redis中的去重,可以大幅度节省内存,对于数据采集这种容错率高的应用来说足够了。bloomfilter高效又节省内存,有点小小的失误率没什么关系。

  • 安装scrapy-redis-bloomfilter
  • 修改配置文件
pip install scrapy-redis-bloomfilter

# scrapy redis 配置
SCHEDULER = "scrapy_redis_bloomfilter.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis_bloomfilter.dupefilter.RFPDupeFilter"

# redis://[user:pass]@host:port/db
REDIS_URL = 'redis://@localhost:6379'

# Schedule requests using a priority queue. (default)
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'

# Alternative queues.
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'

# 持久化,不自动清空
SCHEDULER_PERSIST = True

# Store scraped item in redis for post-processing.
# ITEM_PIPELINES = {
#     'scrapy_redis.pipelines.RedisPipeline': 300
# }

# Number of Hash Functions to use, defaults to 6
BLOOMFILTER_HASH_NUMBER = 6
# Redis Memory Bit of Bloomfilter Usage, 30 means 2^30 = 128MB, defaults to 30
BLOOMFILTER_BIT = 30

我这里用了31,258Mb内存可以去重2个亿吧,足够了。但是,经验告诉我,不能完全依赖这个,最好还是自己存个requests的记录,方便以后增量去重,可以用mysql, mongodb, 甚至redis。