Apache Cassandra是一种快速且可扩展的数据库,多年来,它变得与传统SQL数据库一样容易使用。 至少在表面上。
您使用类似SQL的查询,但是它们有很多限制; 您有一个模式,但是修改它并不像在SQL数据库中那样灵活; 您具有带有主键的相同表格结构,但是由于分区键和排序键之间的区别,因此更加复杂。 乍看之下,有很多底层细节并不重要,但它们对于性能和数据一致性至关重要,例如墓碑,SSTable压缩等。
但是我想讨论“列表”列类型,因为最近我们遇到了一个非常难以捉摸的问题。 我们致力于保证数据的完整性,这就是为什么我们的记录永远不会更新的原因。 这很适合Cassandra,因为要正确地进行更新很棘手。 但是,在我们的一个部署中,我们注意到了一些奇怪的事情–很少有,在与索引数据进行比较时,数以百万计的特定条目中的数据散列将不匹配。 经过调查,我们注意到“列表”类型的列具有重复值。 这不是代码的问题,因为在这种特殊情况下,代码始终使用Collections.singletonList(..)
似乎Cassandra试图变得更聪明,并且当在批处理插入中看到相同的条目时,它试图合并它们,而不是覆盖彼此,而是尝试将它们合并,从而产生具有重复条目的列表。 有关此问题的报告在此处和此处 。
现在,批处理是一个困难的话题,而看起来却很简单却不是的事情之一。 在大多数情况下, 批次是反模式 。 在某些情况下,批处理是有用的 ,但是它比预期的少得多。 那是由于Cassandra的分布式性质。 另一个麻烦来自于您使用的是令牌感知客户端还是令牌感知客户端策略,即您的客户端是否知道每个记录所属的位置以便向其发送请求。 我不会详细介绍批处理,因为在这两篇链接的文章中对批处理进行了很好的解释。
返回列表–由于在我们的案例中我们没有相同的记录,因此该问题很可能是由于网络超时而导致的,此时客户端未收到写入确认,而是再次尝试再次发送相同的语句。 我不确定是否批量处理。 但是,假设有批次或无批次可能会更安全。 即列表可以在意外情况下合并。
这是根本不使用列表的严重原因。 沃尔玛给出了其他参数
集应优先于列表,因为集(和地图)应避免
写前读模式用于更新和删除
这仅适用于少量物品。 对大量(例如数千个)项目使用集合是另一个问题,因为您无法分批加载项目-可以一次读取所有项目。
例如,在Java应用程序中,即使基础列的类型为List,也可以轻松地用Set替换List,这将暂时避免出现问题-数据仍可能在数据库中重复,但是至少应用程序会使用独特的价值观。 但是请记住,Java Set不能保证排序,因此,如果这对您的逻辑很重要,请确保按照定义明确的比较标准进行排序。
“避免清单”(和“避免批次”)的一般建议可以准确地描述Cassandra。 它看起来易于使用,但是一旦投入生产,您可能会意识到存在一些次优的设计决策。
翻译自: https://www.javacodegeeks.com/2019/02/avoid-lists-cassandra.html