前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Delta 如何解决并发写冲突(乐观锁)

Delta 如何解决并发写冲突(乐观锁)

作者头像
用户2936994
发布2022-04-02 15:53:14
6370
发布2022-04-02 15:53:14
举报
文章被收录于专栏:祝威廉祝威廉

首先,delta不存在读写冲突。原因是因为在Delta中写不影响读。那为什么Delta写不影响读呢?很简单,delta能够保持版本,而且版本随着写入不断递增,之前的版本不会有变化。这意味着你读的那一瞬间,后面有什么新写入,你肯定是看不到的,后面有什么删除,也不会对你有影响。

那么delta真正需要解决的是并发写冲突。一般而言,写分成三种情况:

  1. 需要读取当前表的数据,然后计算,接着写入新的文件,删除旧的文件。这种模式典型的是upsert操作。
  2. 只是写新文件,不会使用表已有的数据。这种模式典型的append操作。
  3. 删除数据,会使用当前表的数据,删除旧文件。

一个复杂的commit可能存在(1,3),(2,3) 组合。

假设有两个写操作A,B, 假设他们都是1操作,这意味着他们都需要依赖当前的历史数据。这个时候,他们都会各自进行操作,在最后进行commit操作的时候,只会有一个成功,失败的那个只有两个选择:

  1. 抛出异常,进程退出
  2. 重试。重试主要是重新读取包含新commit的数据,然后再次进行写操作。

如果A是1,B是2, B失败了,只要重新进行commit就好,而无需在进行完整的写操作。而如果A失败了,那么A需要走完整的写流程。

如果A是2,B也是2,那么失败一方都只需要重新进行commit操作,而不需要在重新生成数据。

对于包含3的动作,处理方式和1一样。

另外,值得注意的是,A,B两个写动作,可以在不同的Spark实例,也可以在相同的Spark实例。上面的处理机制都是通用 的。但是同一个实例的A,B并发写动作,可以使用内存中的锁,从而可以等待对方释放锁,而无需像上面那样。

这点也是Delta 做的比较好的地方,这意味着你可以不同实例对同一个delta表进行不同类型并发的写,同时还不影响数据的并发读。缺点也比较明显,很多写操作是比较重的,比如upsert,失败了之后要重新基于新更新的数据做计算,然后再次尝试进行commit操作,所以写的并发度是很低的。

关于delta的版本,本质上是每次写入的时候就会搞一次commit,每次commit就形成了一个版本。读的时候可以读最新版本,也可以读以前任意一个版本。每个版本都相当于一个SNAPSHOT,他会重放当前版本以及之前版本的文件操作从而得到该SNAPSHOT。Delta会定期将老的版本删除(七天之前的),同时还会降多个commit合并成一个文件,方便更加快速的读取。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档