Golang-无限缓存channel的设计与实现

本文探讨了在Go语言中设计和实现无限缓存Channel的需求与挑战,包括不阻塞写入、无数据时阻塞读取、读写操作通过Channel以及自适应扩缩容的双向环形链表设计。文章详细介绍了内部结构、工作原理以及扩容和缩容机制,确保数据的FIFO原则。
摘要由CSDN通过智能技术生成

无限缓存channel的设计与实现

一.引言

Go语言的Channel有两种类型,一种是无缓存的channle,一个种是有缓存的channel,但是对于有缓存的channle来说,其缓存长度在创建时就已经固定了,中间也不能扩缩容,这导致对某些特定的业务场景来说不太方便

业务场景如下 :

  • 爬虫场景,想爬取某个URL页面上可达的所有URL
  • 一个channle中存在待处理的URL
  • 一堆worker groutine从channle中读取URL,下载解析网页并且提取URL,再把URL放入channle

这种场景下,使用消息队列或sync包可以解决这个问题,但是比较复杂,如果有一个可以无限缓存的Channle或许是比较好的解决方案

二.设计

基于以上特定的业务场景,我们的无限缓存Channle应该满足以下要求:

  • 缓存无限,最核心的基本要求。
  • 不能阻塞写,普通channle的写操作之所以阻塞,是因为缓存满了,无限缓存的channle不应该存在这个问题。
  • 无数据时阻塞读,此特性保持和普通channle一样。
  • 读写都应通过channle操作 :通过channle的 <- 和 ->,第一个是方便,仍遵循普通channle的语法,第二是不能暴露内部缓存
  • channle被关闭后,未读取的数据应该仍然可读,此特性和普通channle保持一致
  • 可基于数据量自动扩缩容,在数据量很大的时候要求可以自适应的扩容,在数据量变小后,为了避免内存浪费,要求可以自适应的缩容

针对以上要求,设计思想如下:

  • 内部含有两个普通channle,分别用于读写,我们将其称作In和Out,往In中写入数据,然后从Out中读取数据
  • 内部有一个可以自适应扩缩容的buf,当写channle满了写不了之后,写入到此buf中
  • 内部含有一个工作goroutine,总是In中数据放入到Out或者buf中

内部的自适应扩缩容buf可以采用双向环形链表

和采用数组实现相比,优点如下:

  • 数组大小是有限制的,语言层面就做不到真正的无限缓存
  • 数组扩容代价大,而采用双向环形链表则只用增加节点即可,缩容同样
type T interface{}

type UnlimitSizeChan struct {
bufCount int64    // 统计元素数量,原子操作
In       chan<- T // 写入channle
Out      <-chan T    // 读取channle
buffer   *RingBuffer // 自适应扩缩容Buf
}

双向环形链表 如何写入和读取数据&#x

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值