请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于去重的问题

老师您好, 课程很好, 已经学完了, 回过来做去重有点疑惑.
我理解的去重的本质是是找个容器visitedUrls把访问过的url存起来, 下一个url去看一下这容器里有没有.
那05:30说的worker去调去重, 会不会有多个goroutine并发访问容器visitedUrls?
09:14时说, 把map换成redis, 在多个goroutine中访问, 好像也会有同步的问题?
还有, 05:57说并发版的爬虫各自调自己的去重服务是什么意思, 可以有很多个去重服务?

正在回答 回答被采纳积分+3

1回答

ccmouse 2020-05-05 17:18:52

谢谢同学的支持。

如果让每个worker去调用去重,的确需要处理并发的问题。需要加锁来保护。

把map换成redis的话是不需要处理同步问题的。redis当然能够支持并发访问。只是对于同一个key的值并发访问,我们可能需要在redis层面做一下保护,但是我们去重服务一般会把url或是url的hash作为key,值无关紧要,不存在对同一个key的值并发访问的问题。

还有各自去调去重服务,不一定是多个,一般一个去重服务就够了,所有的worker都可以去调它。

0 回复 有任何疑惑可以回复我~
  • 提问者 linzexin #1
    谢谢老师回答, 对于redis不需要处理同步问题还是有点不理解?在goroutine中
    {
        //1.查下redis是否爬取过, 我用redis的set存放
        if redis.Do("sismember", "zhenai", reqeust.Url) == 0{
            //2.没爬去过, 先写入到redis中
            redis.Do("sadd", "zhenai", request.Url)
            //rpc调用处理
       }
    }
    在第2步没写入成功前, 不是也有可能其他goroutine写入同样的url吗?
    redis层面做保护, 具体怎么做呢?我要先查到了url有没有处理过, 没有再将url添加到redis中, 这两步的原子性怎么保证呢?
    麻烦老师指点下!
    回复 有任何疑惑可以回复我~ 2020-05-05 18:29:44
  • ccmouse 回复 提问者 linzexin #2
    比较自然的做法是key是url,value是bool,并且只要插入的记录,value都是true。所有的记录插入都是原子性的,就保证了并发安全。
    如果我们要考虑namespace,比如zhenai, xcar,最简单的方法就是在key上加上前缀,key=zhenai_http://www.zhenai/..., value=true
    
    如果要使用set也不是不可以,其实只需要用sadd一个命令就行。文档在https://redis.io/commands/sadd 文档里说,sadd会返回到底成功添加了几个元素。所以sadd==1,就说明不存在。可以看一下文档最后的例子
    回复 有任何疑惑可以回复我~ 2020-05-08 20:38:34
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信