V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
V2EX  ›  cloudzhou  ›  全部回复第 1 页 / 共 103 页
回复总数  2041
1  2  3  4  5  6  7  8  9  10 ... 103  
❮ ❯
https://chatgpt.com/share/6aeae799-2e2c-83e8-842e-4ed59b47ccca

ai 分析蛮有意思,我是理清每个人的逻辑了

参与者 最突出的贡献 我的评价
@imchuncai ( OP ) 提出双锁协议,尝试实现强一致 Cache 技术创造力强,但系统级正确性尚未证明
@zzhirong 发现竞态、修正判断、讨论消息原子性 最像认真做协议 Review 的人
@cloudzhou CDC 、版本号、异步处理、工程取舍 工程经验视角强,但部分论证依赖时间窗口假设
@dlyxy 指出 Raft ReadIndex 、脑裂和形式化验证 分布式系统审查方向很准确
@valord577 强调真实业务价值与选型 业务判断正确,技术分析不够深入
@lesismal 指出读后使用期间仍可能过期 业务语义问题成立,但结论过于绝对
1 天前
回复了 Bssn 创建的主题 › 分享发现 › 被 AI 狠狠辱骂了 🤡
最后总结一下你这个人:

你是一个典型的:
- 技术上极度较真,生活上随机开坑。
- 喜欢把简单问题研究成复杂系统。
- 对参数特别敏感,对上下文特别吝啬。
- 永远觉得还有一个细节没搞明白。
- 看见一个新技术,就想把它拆开看看里面是不是还有一层。
你最大的技术优势是好奇心。

你最大的技术缺陷也是好奇心。
2 天前
回复了 aw2350 创建的主题 › Claude › 用 deepseek 的 api+ccswitch 效果怎么样?
你这个谁也回答不上来,充个 100 块钱当沉没成本,找个小需求改一下,能用继续充,不能用适可而止
别看段子太多,程序员这体格,跑外卖都不大行
@imchuncai 是的,但是流程简化了好多,可以考虑作为工程实践了,有意思
@zzhirong 我的设计之前没有说的很清楚,就是 “由 CDC 中间件去发送更新/删除的消息”,消息二次汇总然后统一一个处理点,不管是 读写过期,都是一个 get by id 然后 cas

@imchuncai 刚才我让 ai 帮我分析了一下,发现你 #43 的设计除了短暂不一致,居然是可行的,整个就简化很多了,有点意思
@imchuncai 你很适合做一致性高的业务,这个考验很多设计细节,很多人都不会考虑一致性的
@imchuncai 严格从并发安全看这个不够的,这是我之前一个妥协方案,“引入一个延迟周期”,只是说尽量避免
Get cache miss:
1. Get DB
2. set Cache
3. Get DB
4. set cache cas and only exists

这个不知道什么逻辑? get 两次?
@imchuncai 除了你说的,“发送 event Z 失败” 这种情况,目前最终一致是可以做到的,你再看看我的方案。

而我的意思,你不能把这个失败也纳进来讨论,可以说失去讨论意义了。
@imchuncai

续期的意思就是 GETEX 传入相同的过期时间
过期时间是否相同一点都没影响啊,下次更新就是新的数据了,我们的核心是,旧数据最多 ttl 时间内
你的意思是每次 get 的时候,还延续 ttl ?这个我的实践上,没有这么做的

---
你不能把发送 event z 失败,这个事情纳进来,正如 raft 脑裂整个系统失败了一样。
这么说的话不用举这么复杂的例子,只要 version=1 事件设置 cache 成功,version=2 事件因为各种原因失败就行了,缓存已经不一致

CAP 理论里,只能有两个,而 cache ,实践上都是纳入弱一致性范围。
@imchuncai

你一旦提供 ttl ,你就没法处理用户会续期的行为
cache ttl 是没有续约概念的,只会中途刷新,或者到期消失,影响范围只有 ttl 时间

我再次总结不出现 ttl 范围 cache 不一致的设计:

触发事件然后缓存集中处理,也就是没有并发态:
1. 读触发 cache 更新,触发 event: (read, table, id)
2. 驱逐、写触发 cache 可能更新,触发 event: (write/volatile, table, id)
3. 事件流式处理,同一个 table 事件只有一个进程顺序处理
4. 无论是 1 ,2 事件,从 db 拉去新数据,read 操作直接 cas 更新 cache ,write/volatile 一样,cas and only exists

重点:同一个 table 只有一个处理点,消息不管先后乱序,都是 select by id 拉最新数据和 cache 同步
@imchuncai

1. 我的 append 还有两个实现,那个是解决最终一致
2. mysql by id 是真的快,尤其是已经在 innodb cache ,问题是 db 很宝贵,让 db 做事务严格一致的行为
3. etcd 只是一个例子,因为他们就是 raft 协议,只要你要 raft 就存在多节点协商,其实你这个 case ,没有用 raft 的需要
4. raft 所谓的锁,等于一个写指令,对你这里来说也等于多点协商
5. qps 就是最重要的事情,衡量一个技术方案是否可行,对 qps 要有一个非常直观的了解,经典的 Latency Numbers Every Programmer Should Know
https://gist.github.com/jboner/2841832
同样可扩展到对于 raft 、redis 、mysql 读写的 qps 的时延衡量
10 月 30 日
回复了 naixiangapp 创建的主题 › 职场话题 › 浙江车企真 j8 事多
@naixiangapp 那你的问题,就应该是提出 bug 被改这个问题,而不是去说关了这个 bug 问题
10 月 30 日
回复了 naixiangapp 创建的主题 › 职场话题 › 浙江车企真 j8 事多
重写 bug 描述,这个不专业

但是:
“是固件问题,不是软件问题,把这个 bug 单关闭吧”

这也不专业,你不能叫测试关闭 bug ,你让测试部门怎么想?
一个具体流程:
开发对于 bug ,解决 or 不需要处理,然后 issue 描述具体上下文,为什么不需要处理,之后交给测试决定就好了

都按流程来,没必要置气,你提你的,我解决我的
@imchuncai
我的强一致是不可能达成这是对的,包括短期的不一致,但是我这个方案,是可以做到最终一致的,你可以看我的 append

数据库持有写锁,和 raft 的锁,差距极大,数据库性能其实比我们想象高很多,还有锁范围也是不同。
反而是 raft ,涉及到多点协商一致,这个 qps 非常低的,etcd 早期都被诟骂,因为有人把它当 kv 用。
raft 作为选举、仲裁大脑,不适合做高 qps 的行为。有很多测评,raft 集群 qps 低于单体 mysql 。

所以我说你这个方案,本质没问题,但是不应该用在 cache 。
cache 这玩意是为了什么,无非就是快,而你把一个 raft 包一下,这,快不起来的。
@imchuncai

Q 不 set 会有更严重的并发问题
A 你这个问题,和监听驱逐事件是一个类型,就是你说的竞争态:
“在短时间,高版本事件的不设置(不管是驱逐还是没有不处理 update 事件到 cache ),导致低版本进行覆盖”

所以这里我有一个简单处理方案:
*** 引入一个延迟周期,只更新 cache 已有的 key ,这样避免持久相互驱逐,同时更新并发竞态数据 ***
等于你的 3. CDC 触发更新,redis 不存在该 key,所以不更新,这一步,是有一个延迟周期的,确保 “理论上” 覆盖 1 ,4 这个 T 时间周期

一句话总结,按需写 cache 操作(驱逐、更新触发),延迟一个周期,以便覆盖可能历史低版本(读触发)

---

当然,这不是真正并发安全。
但是如果真要做到一致性,这个是好做的。逻辑如你实现方案
你看:
version=1 ,事件 1 ,4 ,是一个事务
version=2 ,事件 2 ,3 ,是一个事务

这两个事务都是同一个 data ,在这里面做分布式锁就可以了

---

更简单的工程实现:
触发事件然后缓存集中处理,也就是没有并发态:
1. 读触发 cache 更新,触发 event: (read, table, id)
2. 驱逐、写触发 cache 可能更新,触发 event: (write/volatile, table, id)
3. kafka 集中监控,按照 table 分区,同一个 table 事件顺序处理
4. 无论是 1 ,2 事件,从 db 拉去新数据,read 操作直接 cas 更新 cache ,write/volatile 一样,cas and only exists

mysql 在 select by id 这一块,速度高的超过你估计,这些事件都意味着对应 table, id 刚访问过,再次读取都只是从 db 的 cache 获取
无论是 ttl ,volatile 都可控

你看这个实际的工程事件:
1. 无论读写,对业务都没任何影响,分发事件可以搞个异步,goroutine channel with max length ,消费不了直接丢弃
2. cache 动态可控,消费点做逻辑,无论是 ttl 还是 update 事件是否进入 cache
@valord577 作为技术方案探讨,也很不错了,毕竟,ai 时代,已经不提技术了 :~

他这套方案,有应用场景,但不是 cache ,而是分布式 lock
lock 要做细腻,也有很多细节可思考:
1. 乐观/悲观,读/写锁,最高并发锁?令牌桶?(问号概念是我拍脑袋的)
2. 锁周期,不能导致资源长期不可用
3. 顺序,以及锁关联的 do once
等等

借助 raft 机制下,做一个全局的分布锁 lib ,用在敏感领域,大家用起来如同本地 lock

@imchuncai
昨天有几个问题没有回答:

Q: 而你的方案所有的操作都会对缓存进行写入,我的方案对热点数据更友好,冷数据的修改可能永远都不会触发写入缓存
A: 其实这是策略问题,我收到 update 事件,也可以根据是否在缓存里然后更新,缓存依然是按需的

Q: 驱逐的问题
A: 依然是策略问题
- 可以根据 ttl 尽量避免驱逐(现实中采取方案,因为 cache 驱逐是非常不好的行为,无法确定驱逐的数据是否重要)
- 在驱逐情况下,你提到的并发问题,可以根据监听 redis Keyspace Notifications 然后一个延迟周期,只更新 cache 已有的 key ,这样避免持久相互驱逐,同时更新并发竞态数据
10 月 28 日
回复了 laodao 创建的主题 › 生活 › 男人为啥非要结婚?给你再选一次的机会
@laodao 你父母给管孩子,要看你父母是否一起生活,以及相互付出。如果是传统的男方家庭为主,那么这个过程也就隐含着养老
1  2  3  4  5  6  7  8  9  10 ... 103  
❮ ❯
About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2871 Online   Highest 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 23ms · UTC 13:20 · PVG 21:20 · LAX 05:20 · JFK 08:20
♥ Do have faith in what you're doing.