应用程序日志的Cassandra数据模型(数十亿次操作!)

应用程序日志的Cassandra数据模型(数十亿次操作!),cassandra,data-modeling,Cassandra,Data Modeling,比方说,我想从每秒产生1000-5000条记录的大型应用程序集群收集日志。将来,这个数字可能达到每秒100000条记录,从10000多个数据中心聚合而成 CREATE TABLE operation_log ( -- Seconds will be used as row keys, thus each row will -- contain 1000-5000 log messages. time_s bigint, time_ms in

比方说,我想从每秒产生1000-5000条记录的大型应用程序集群收集日志。将来,这个数字可能达到每秒100000条记录,从10000多个数据中心聚合而成

CREATE TABLE operation_log (
       -- Seconds will be used as row keys, thus each row will
       -- contain 1000-5000 log messages.
       time_s bigint,
       time_ms int, -- Microseconds (to sort data within one row).
       uuid uuid, -- Monotonous UUID (NOT time-based UUID1)

       host text,
       username text,
       accountno bigint,
       remoteaddr inet,
       op_type text,
       -- For future filters — renaming a column must be faster
       -- than adding a column?
       reserved1 text,
       reserved2 text,
       reserved3 text,
       reserved4 text,
       reserved5 text,

       -- 16*n bytes of UUIDs of connected messages, usually 0,
       -- sometimes up to 100.
       submessages blob,
       request text,
       PRIMARY KEY ((time_s), time_ms, uuid)) -- Partition on time_s
-- Because queries will be "from current time into the past"
WITH CLUSTERING ORDER BY (time_ms DESC)

CREATE INDEX oplog_remoteaddr ON operation_log (remoteaddr);
...
(secondary indices on host, username, accountno, op_type);
...
CREATE TABLE uuid_lookup (
       uuid uuid,
       time_s bigint,
       time_ms int,
       PRIMARY KEY (uuid));
我想使用OrderedPartitioner,它将通过
时间(秒)将数据传播到整个集群。随着更多的应用程序日志聚合器添加到应用程序集群,它还必须扩展到数十个并发数据写入程序(PK的
uuid
部分保证了唯一性和一致性)

分析师必须通过执行以下类型的查询来查看这些数据:

  • 时间
    上进行范围查询,对任何数据字段进行筛选(
    从操作日志中选择*,其中时间<$time1和时间>$time2和$filters
  • 从上一次的结果进行分页查询(
    SELECT*from operation_log,其中time_s<$time1和time_s>$time2和token(uuid)
  • 对时间范围内由任何数据字段过滤的消息进行计数(
    从操作日志中选择计数(*),其中时间<$time1和时间<$time2和$filters
  • 按某个范围内的任何数据字段对所有数据进行分组(将由应用程序代码执行)
  • 通过其
    uuid
    请求数十条或数百条日志消息(数百条
    从uuid\u查找中选择*,其中uuid位于[0000000 5-3ecd-0c92-fae3-1f48,…]
我的问题是:

  • 这是一个健全的数据模型吗
  • 使用
    OrderedPartitioner
    是这里的方法吗
  • 为可能的筛选器设置一些列有意义吗?或者每隔一段时间添加一个列是否足够便宜,可以在具有一些保留空间的Cassandra集群上运行
  • 如果并发查询者的数量永远不会超过10,是否有任何东西阻止它从数百个聚合器扩展到每秒100000个插入行,并存储一到两个PB的可查询数据
此数据模型接近正常模型,但有几个重要的修改/注意事项:

  • 不要使用ByteOrderedPartitioner,尤其不要将时间作为键。这样做将导致集群上出现严重的热点,因为您将只对数据范围的一部分(以及集群的一小部分)执行大部分读取和所有写入操作使用第三分区器

  • 要启用范围查询,您需要一个sentinel键——一个您可以提前知道的键。对于日志数据,这可能是一个时间段+其他一些不基于时间的已知值(因此写入是均匀分布的)

  • 你的指数可能还可以,但如果不知道你的数据,很难判断确保您的值基数较低,否则索引无法很好地扩展

  • 确保任何潜在的过滤列都符合低基数规则。更好的是,如果您不需要实时查询,请使用Spark进行分析。您应该根据需要创建新列,因为这不是什么大问题。卡桑德拉稀疏地储存着它们。更好的是,如果使用Spark,可以将这些值存储在地图中

  • 如果您遵循这些准则,您可以根据需要扩展到任意大的规模。否则,您的性能将非常差,并且可能会获得相当于单个节点的性能


非常感谢您!不建议使用BOP,因为它会将密钥空间一分为二(这样,对于两个节点,一个节点总是获取当前写操作,并将一些“旧”数据排放到另一个节点)?是否可以制作一个平均分布数据的切分键,但仍然允许我对PK的前两个组件(秒和毫秒)进行范围查询?另外,请详细说明sentinel键?有时原始日志必须逐页浏览,因此唯一的范围查询键是时间,时间具有可怕的基数。您的键必须生成均匀分布的散列,以避免热点。所以它应该类似于[time\u bucket]:[origin\u host],所以它分布良好,在查询时是可以知道的。不建议使用BOP,因为它会导致负载不均匀(每个节点拥有一系列键,这些键随BOP顺序排列)。提到两个节点让我很困扰,因为三个节点是绝对最小值,即使这样,在生产中也不太合理。这是因为RF=3在大多数情况下都非常理想。origin\u主机在关键点中扮演什么角色?是否必须在范围内选择查询中明确提及它?是的,必须明确命名它。这只是一个例子;您可以选择任何不基于时间的、在查询时可以知道的内容。