V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Kould
V2EX  ›  Java

写了一个开源的面向数据库 IO 的零冗余数据缓存框架,希望大佬们给些意见

  •  
  •   Kould · 2022-06-29 17:49:28 +08:00 · 1800 次点击
    这是一个创建于 910 天前的主题,其中的信息可能已经有所发展或是发生改变。

    业余时间花了一年左右写了一个开源缓存框架 Kache ,主要用于以类似 Spring cache 的使用方式下沉到数据库持久化操作。可以将有限的空间放大应用于更多的缓存上,增强缓存命中率和降低缓存变动成本 仓库地址: https://gitee.com/Kould/kache

    希望各位大佬多多给予意见,能 star 或推荐一下!

    15 条回复    2022-06-30 19:09:52 +08:00
    guisheng
        1
    guisheng  
       2022-06-29 18:34:28 +08:00 via iPhone
    关注一下 开源不易加油,估计后面会被抄袭一个版本
    Kould
        2
    Kould  
    OP
       2022-06-29 18:41:58 +08:00
    @guisheng 感谢支持,不过请问抄袭是指 fork 吗
    dqzcwxb
        3
    dqzcwxb  
       2022-06-29 22:05:06 +08:00
    看了下文档,你想复用在 redis 里面的数据,有一点拙见想说一下
    有没有想过一个问题,哪怕是一样的数据他们的刷新时间和策略是不一样的,比如说 A 和 B 用户的数据相同在你的框架里被指向了同一个数据,但是此时 A 要清空数据那么问题来了 A 和 B 的数据是同一个,A 删除数据 B 也没了,A 不删除数据那么数据怎么判定为空后重新拉取刷新?
    类似的问题应该还有很多,感觉会很影响业务
    fpure
        4
    fpure  
       2022-06-29 23:09:05 +08:00
    这玩意儿花了一年?你是怎么做到的
    NoBugDie
        5
    NoBugDie  
       2022-06-30 00:05:54 +08:00
    已 star ,有空来研究一下
    Kould
        6
    Kould  
    OP
       2022-06-30 09:47:35 +08:00
    @dqzcwxb 本身定位的话仍然是主要面向数据库 IO 的,而您说的问题大多是牵扯到外键,本身这个框架是可以与 Spring Cahe 结合,可以做到 Spring Cache 负责 Service 层用于外键的 Bean 装填处理,而 Kache 应当做好的是对数据库的一层旁路,用于最大化避免数据重新走入数据库之中,目前 Kache 对于数据的感应都是通过应用的,也是兼容分布式的,但是如果是外置工具操作数据库的话确实可能会导致数据变化而 Kache 无法感知,后继有使用 binlog 等手段的可能。
    简而概之就是尽可能不要要外键填充的操作放入的持久化操作之中,否则持久化的方法难以复用并且会导致数据千变万化,Kache 本身注解有个 involve 属性用于干涉其他 Bean 类型缓存的清除,但尚未有完美解决这个问题的方案
    Kould
        7
    Kould  
    OP
       2022-06-30 09:48:51 +08:00
    @fpure 项目驱动学习,原型只是一个 AOP ,再逐渐变成 spring starter 再分离变成 Proxy 与 spring starter
    fzdwx
        8
    fzdwx  
       2022-06-30 09:49:55 +08:00
    @Kould 昨天看到老哥 star 了我写的 `websocket spring boot starter`哈哈,好巧。
    Kould
        9
    Kould  
    OP
       2022-06-30 09:52:12 +08:00
    @fzdwx 因为看到了你的浏览记录,感觉 websocket spring boot starter 很不错,所以 star 了一下
    dqzcwxb
        10
    dqzcwxb  
       2022-06-30 09:52:24 +08:00
    @Kould #6 所以这个问题其实没法完全参考 jvm 里的对象管理概念,因为业务缓存的一致性不仅仅是在于数据内容还有过期时间和刷新策略所以单纯的用数据内容做对比去实现复用会出现问题
    如果要强行解决这个问题,应该是需要在 update 的同时进行判断是否需要 insert 新的数据跟旧数据分离,这又会带来新的原子性问题
    感觉很难完美处理,期待你的解决方案
    Kould
        11
    Kould  
    OP
       2022-06-30 10:02:17 +08:00
    @dqzcwxb 在过期时间上的处理话,在存入缓存时会先向 redis 中去重,得到缺少的数据再存入,而重复的 id 则会延长存活时间。而刷新策略目前属于较为悲观的该类型所有索引缓存全删,不过相对于 spring cache 的缓存删除成本来说小很多。目前的数据冗余判断依据是依照数据库中主键的概念,做不到非常深层次的数据重用。
    dqzcwxb
        12
    dqzcwxb  
       2022-06-30 10:27:39 +08:00
    @Kould #11 "而刷新策略目前属于较为悲观的该类型所有索引缓存全删"你这句话让我想到这篇讲 myabtis 二级缓存的文章 https://blog.csdn.net/isea533/article/details/44566257
    Kould
        13
    Kould  
    OP
       2022-06-30 10:39:04 +08:00
    @dqzcwxb 是的,这就是我所不满意 Spring Cache 所作的:“将命名空间下所有缓存删除”;这篇文章中“针对一个表的某些操作不在他独立的 namespace 下进行。”这句话也就是之前所说外键之间的无奈,所以我仍然认为 service 中进行外键数据填充操作是最佳实践。
    不过言归正传,Kache 因为缓存实体是分离的,对于条件方法之间的缓存是以索引的形式再次指向实体的结构,因此当实体更新时不会像 spring cache 将缓存全盘删除,而是仅仅将多个条件方法的“索引缓存”(类似一个 list<指针>)删除掉,相较于 spring cache 来说可以避免缓存的重复序列化而可以再删除后写入缓存时只需要存入索引缓存即可,避免数据序列化和冗余。并且因为获取缓存脚本与本身缓存结构,缓存删除与读取是无锁并行的。
    THESDZ
        14
    THESDZ  
       2022-06-30 16:08:31 +08:00
    好家伙,倒序索引?那可以优化 参数->id 这个映射,参考 elasticsearch bitmaps/roaring bitmaps
    Kould
        15
    Kould  
    OP
       2022-06-30 19:09:52 +08:00
    @THESDZ 学习到了,非常感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1049 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:39 · PVG 03:39 · LAX 11:39 · JFK 14:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.