dougou3871 2016-10-28 08:50
浏览 145

Golang Web服务器和内存缓存的并发方法

I am not new to programming, but I am relatively new to golang and still not completely used to the golang concurrency approach.

The general set-up:

  • Web server (should be fast and parallel), so I use net/http
  • I need to store and retrieve lots of documents. While retrieving happens more often than storing, the factor is rather low. Maybe 20.
  • When retrieving the, by far, most important are the lastly stored documents. The rest can be retrieved just from the disk/DB if needed.
    • Solution: In memory cache of last added items.
    • Note: On retrieval, I don't care about the last 3 seconds. Meaning, if, at time (A), I ask for a complete list of the last added items, the items added in the last 3 seconds can (partially or completely) be missing. But when asking again at time (A+3s) all those items should be in the list.

My question is related to how to implement the in memory cache.

Naive approach #1 (RWLock)

  • Have a big list of items in memory.
  • Guard it with a RW lock

Problem with this approach: I successfully serialized the web server :)

OK, please forget about this approach.

Approach #2: Split things up

  • have X lists in memory (each with RWLock)
  • on http handler start get a random number and chose one of the X lists, work only on that list
  • Another collector routine is started every 2.5 seconds collecting and combining the lists

This is better, I theoretically could even split the work between servers.

But, for example based on the golang tour code:

func main() {
    http.HandleFunc("/view/", makeHandler(viewHandler))
    http.HandleFunc("/edit/", makeHandler(editHandler))
    http.HandleFunc("/save/", makeHandler(saveHandler))
    http.ListenAndServe(":8080", nil)
}

How do I pass/get a new random number in the http handler without serializing?

  • It does not need to be cryptographically secure. I just want to use it to pick one of the X lists.
  • I know there is a global random generator but that uses a mutex internally, so back to square 1.
  • I could ask the clients (JavaScript) to provide a random number as get parameter. But that sounds dangerous (DOS)? Or is this OK?
  • I might not know the users IP address in the go server (reverse proxy setup).

And: Generally is this a good approach? Is there a better way? And now I am limiting myself to X, this does not scale. If I want X to change during run-time, how could I tell the handlers about that change (without becoming serial again)?

  • 写回答

1条回答 默认 最新

  • duanlou7910 2016-10-28 13:46
    关注

    You don't really serialize your server with RWLock. Use RLock() for parallel read of documents.

    Check on thread-safe concurrent map for go library. It utilizes mutex and sharding technics alongside. I would also added CQRS to database level and It could easily handle 100K concurrent requests/sec.

    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c