V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
seaguest
V2EX  ›  Go 编程语言

开源一下自己的 Go 分布式缓存方案

  •  
  •   seaguest · 2019-08-27 17:32:48 +08:00 · 6300 次点击
    这是一个创建于 1917 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近整理了一下自己的分布式缓存方案,主要是内存+redis 二级缓存,支持多机同步,目前已经在线上投入使用,经过百万日活的验证。

    内存部分是采用的是 sync.Map, 读取缓存的时候先从内存读,如果未读到则去读 redis,如果 redis 未读到,则根据定义的加载函数加载到 redis 和内存。

    缓存有 lazy 模式,为了避免缓存被击穿,可以设置 lazy 模式,缓存数据存活的时间更久,但是每次读取的时候依然会判断数据是否是最新的,不是最新的话会异步加载更新。

    通过 redis 的 Publish/Subscribe 功能,实现缓存的分布式更新,目前仅实现删除同步。

    项目地址 https://github.com/seaguest/cache

    欢迎大家批评指正!

    17 条回复    2019-09-05 08:12:51 +08:00
    gowk
        1
    gowk  
       2019-08-27 17:40:07 +08:00 via Android
    Gopher, Follow 了~
    kevin1234
        2
    kevin1234  
       2019-08-27 17:53:47 +08:00
    多机内存中的数据也会同步?
    seaguest
        3
    seaguest  
    OP
       2019-08-27 17:57:07 +08:00
    @kevin1234
    这个不会,所有机器共享 redis,各自维护自己的内存缓存。
    通过 Delete 可以删除所有机器中指定 key 的缓存,可以保障下次该 key 被访问时是最新的数据。
    MarkOrca
        4
    MarkOrca  
       2019-08-27 18:12:26 +08:00
    高并发情况下 subscribe 可以保证数据一致么?
    wweir
        5
    wweir  
       2019-08-27 18:23:23 +08:00
    正在考虑,直接集成 dragonboat,废了 redis,以实现写少读多场景下的高性能缓存,并真正解决缓存层的强一致问题。
    jziwenchen
        6
    jziwenchen  
       2019-08-27 18:56:32 +08:00
    学习下
    seaguest
        7
    seaguest  
    OP
       2019-08-27 19:22:53 +08:00
    @MarkOrca
    这个之前测过 1000 并发的,主要是读。如果写不是很频繁的话,理论上应该没什么问题。
    seaguest
        8
    seaguest  
    OP
       2019-08-27 19:24:46 +08:00
    @wweir

    我这个是轻量级的缓存,主要是以读为主。
    更新的话,目前是直接写数据库,然后删除对应的缓存,下次访问缓存未命中直接查询数据库就可得到最新的数据。
    blless
        9
    blless  
       2019-08-27 19:30:04 +08:00 via Android
    我好像也写过一个来着,本机加了一个超时控制,redis 做业务锁控制读写,所以并发还是受限于 redis
    swulling
        10
    swulling  
       2019-08-27 19:33:58 +08:00 via iPhone
    可以试试 Redis 新版本的客户端缓存,就不用业务自己写缓存
    iPhoneXI
        11
    iPhoneXI  
       2019-08-27 19:37:30 +08:00
    @seaguest #8 缓存更新是不是用 Cache Aside Pattern 更好
    https://coolshell.cn/articles/17416.html
    seaguest
        12
    seaguest  
    OP
       2019-08-27 19:43:10 +08:00
    @iPhoneXI

    是的,目前采取的就是这个策略,只不过加了内存->redis 两层。
    更新目前直接操作数据库,然后调用 Delete 使其失效。
    HackerZ
        13
    HackerZ  
       2019-08-28 09:15:40 +08:00
    我也做了一套类似的解决方案,使用 checksum 解决了多节点内存数据不一致的问题~
    chennqqi
        14
    chennqqi  
       2019-08-28 10:04:10 +08:00
    1000 并发是不是少了一点。。。
    seaguest
        15
    seaguest  
    OP
       2019-08-28 10:13:56 +08:00
    @chennqqi

    这个只是我之前的测试数据,可以更高。
    性能的瓶颈在于请求 DB 的相关逻辑以及 redis 的处理能力,如果 DB 查询没什么问题,redis 单机 10 万 QPS 应该都不是问题。
    MarksGui
        16
    MarksGui  
       2019-09-04 11:50:14 +08:00
    不错,学习下
    T3RRY
        17
    T3RRY  
       2019-09-05 08:12:51 +08:00
    +1
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3900 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 00:56 · PVG 08:56 · LAX 16:56 · JFK 19:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.