Backgound :我们正在使用Cassandra存储一些时间序列数据,我们正在使用预准备语句来访问数据。
我们通过以下方式对表中的数据进行分区:
使用不同的表我们需要为查询,时间段和保留策略的每个组合准备(仅在使用时)不同的语句,因此我们将准备好的语句数量激增。一些数学:
timePeriods = 12..52 * yearsOfData
maxNumOfPrepStatements = timePeriods * policies * numOfQueries
ourCase => (20 * 10 y) * 10 p * 10 q = 20.000 prep statements
在客户端,我只能在缓存中保留最常用的PS,但是我找不到从服务器中删除未使用的PS的方法,所以我担心有大约20.000个准备好的语句对每个人来说都是一个很大的代价。节点。
问题:这个PS的数量是否会导致服务器出现问题?
这会导致较小的问题:
答案 0 :(得分:4)
这些准备好的声明的服务器端成本是多少?
每个预准备语句将被解析,并使用MD5摘要作为关键字进一步存储在缓存中。客户端关于重新注册的相同准备语句将使服务器将MD5摘要与现有语句匹配,因此应该避免。执行已注册的语句将使客户端将MD5连同查询参数一起发送到服务器,并且服务器能够使用MD5检索缓存的语句,与解析常规CQL语句相比,执行速度更快。每个缓存的语句也将使用部分Java堆,它对应于MD5键的总大小和语句对象的表示。
服务器会保留所有PS还是删除较少使用的PS?
预备语句由服务器通过基于ConcurrentLinkedHashMap创建缓存来管理。缓存的容量取决于可用内存:Runtime.getRuntime().maxMemory() / 256
。条目也按其内存使用情况加权,并且在达到容量的情况下,将首先从缓存中逐出大型语句。您可以使用org.apache.cassandra.metrics.CQL.PreparedStatementsEvicted
JMX指标监控此行为。
有没有比重新启动Cassandra节点来清理PS缓存更好的解决方案?
不是我知道的。我也不确定你为什么要这样做,因为将为相同的查询创建相同的MD5摘要。另请注意,Java客户端将自动re-register prepared statements在服务器上找不到,例如如果它已从缓存中逐出(参见this answer)。
使用Java客户端,关闭Session / Cluster对象会减轻这个(服务器端)吗?
我不这么认为。服务器必须跟踪数百个潜在客户已注册的语句,以便安全地清理它们。