RDBMS嵌套插入的Cassandra方法

RDBMS嵌套插入的Cassandra方法,cassandra,nosql,Cassandra,Nosql,我定期收到两类数据集: 网络流量,每秒数千: { 'stamp' : '2017-01-19 01:37:22' 'host' : '192.168.2.6', 'ip_src' : '10.29.78.3', 'ip_dst' : '8.8.4.4', 'iface_in' : 19, 'iface_out' : 20, (... etc ..) } 和接口表,每小时: [ { 'stamp' : '2017-0

我定期收到两类数据集:

网络流量,每秒数千:

{
    'stamp' : '2017-01-19 01:37:22'
    'host' : '192.168.2.6',
    'ip_src' : '10.29.78.3',
    'ip_dst' : '8.8.4.4',
    'iface_in' : 19,
    'iface_out' : 20,
    (... etc ..)
}
和接口表,每小时:

[
    {
        'stamp' : '2017-01-19 03:00:00'
        'host' : '192.168.2.6',
        'iface_id' : 19
        'iface_name' : 'Fa0/0'
    },{
        'stamp' : '2017-01-19 03:00:00'
        'host' : '192.168.2.6',
        'iface_id' : 20
        'iface_name' : 'Fa0/1'
    },{
        'stamp' : '2017-01-19 03:00:00'
        'host' : '192.168.157.38',
        'iface_id' : 20
        'iface_name' : 'Gi0/3'
    }
]
我想在Cassandra中插入这些流,根据最新匹配的host/iface_id值,使用接口名而不是id。我不能依赖于只使用内存的解决方案,否则每次重新启动应用程序时可能会释放多达一小时的流

我想到的是使用两个Cassandra表:一个保存流,另一个保存最新的host/iface_id表。然后,当接收到流时,我将使用此数据正确填充接口名称

理想情况下,我想让卡桑德拉来处理这件事。在我看来,它似乎比每次从应用程序端提取接口名更有效

问题是我不知道如何做到这一点——而且我以前从未使用过NoSQL,我甚至不确定这是否是正确的方法。。。有人能给我指出正确的方向吗


在接口表中插入数据并只保留最新版本是非常简单的,但我不能将注意力集中在“在流记录中插入接口名称”部分。在传统的RDBMS中,我会使用嵌套查询,但在Cassandra中似乎不存在这些查询。

阅读您的问题,我希望interface表中每小时接收的数据不会太大。所以我们可以将数据(单行)保存在内存中,也可以保存在cassandra数据库中。对于每一个小时,内存中的数据将得到更新,并将一个新的数据插入到数据库中。我们可以使用下表定义保存接口数据-

     create table interface_by_hour(
        year int,
        month int,
        day int,
        hour int,
        data text, -- enitre json string for one hour interface data.
        primary key((year,month,day,hour)));
很少有insert语句--

在此表中保留每小时一次的接口数据,并在内存中进行更新。拥有内存数据的好处是,您不必每秒从表中读取数千次数据。若应用程序宕机,您可以使用下面的查询从表中读取当前/前一个小时的数据,并构建内存缓存

    cqlsh:mykeyspace> select * from interface_by_hour where year=2017 and month=1 and day=27 and hour=0;

     year | month | day | hour | data
    ------+-------+-----+------+--------------------------
     2017 |     1 |  27 |    0 | {complete json.........}
现在是流量数据--

因为我们在内存中缓存了当前的小时接口表数据,所以我们可以快速地将接口名称映射到主机。使用下表保存流量数据

    create table flow(
    iface_name text,
    createdon bingint, -- time stamp in milliseconds.
    host text, -----this is optionl, if you want dont use it as column.
    flowdata text, -- entire json string 
    primarykey(iface_name,createdon,host));
我在上表中看到的唯一问题是,它不会在分区之间均匀地分布数据,如果一个接口名有太多的流数据,那么整个数据将插入到一个分区中

我设计这个表只是为了保存数据,如果你能指定如何使用这些数据,我会做更多的思考


希望这会有所帮助。

据我所知,接口数据的写入量不会太大,因此需要按时间进行分区。它每小时仅更改一次,因此无需将每小时的数据保存为最新版本。此外,我将假设您希望以某种方式对此进行查询,我不确定如何进行查询,因此我将为接口提出一些一般性建议,并将威胁作为时间序列数据的流:

create table interface(
    iface_name text primary key,
    iface_id int,
    host text, 
    stamp timestamp
);

insert into interface(iface_name, iface_id, host, stamp) values ('Fa0/0', 19, '192.168.2.6', '2017-01-19 03:00:00');
insert into interface(iface_name, iface_id, host, stamp) values ('Fa0/1', 20, '192.168.2.6', '2017-01-19 03:00:00');
insert into interface(iface_name, iface_id, host, stamp) values ('Gi0/3', 20, '192.168.157.38', '2017-01-19 03:00:00');
通常这是卡桑德拉的安蒂帕特伦:

cqlsh:test> select * from interface;

 iface_name | host           | iface_id | stamp
------------+----------------+----------+---------------------------------
      Fa0/0 |    192.168.2.6 |       19 | 2017-01-19 02:00:00.000000+0000
      Gi0/3 | 192.168.157.38 |       20 | 2017-01-19 02:00:00.000000+0000
      Fa0/1 |    192.168.2.6 |       20 | 2017-01-19 02:00:00.000000+0000
但据我所知,你没有那么多的接口

所以,基本上,在最坏的情况下,任何高达数千的东西都可以 使用token函数从分区中取出数据,但问题是这样可以节省您的时间 大量的空间,你不需要按小时保存

我会简单地将这个表也保存在内存中,然后在它进入时充实数据。 如果有更新,请更新内存缓存。。。但也给卡桑德拉写了信。 若出现故障,只需从接口表中恢复并继续

基本上你的流量信息会变成

{
    'stamp' : '2017-01-19 01:37:22'
    'host' : '192.168.2.6',
    'ip_src' : '10.29.78.3',
    'ip_dst' : '8.8.4.4',
    'iface_in' : 19,
    'iface_out' : 20,

    'iface_name' : 'key put from in memory cache',
}
这就是您将如何获得最大的性能现在节省流量只是 时间序列数据,然后,考虑到你是击中集群 每秒数千次,当你按时间分割时 在(使用模型)中,每秒至少获取7000列(如果不是更多的话) 我在这里建议)通常你会想要有多达100000个专栏 在单个分区内,这意味着您的分区已被覆盖 20秒甚至更少的理想尺寸,所以我甚至建议使用 随机桶(插入时仅使用定义范围内的某个数字 比如说10):

如果希望随时间获取流,只需使用 时间戳加上同时进行10次查询或逐个查询以访问所有数据。这里有各种各样的技术,您只需要告诉更多关于您的用例的信息

然后插入类似于:

insert into flow(time_with_minute, artificial_bucket, stamp, host, ip_src, ip_dst, iface_in, iface_out, iface_name)
    values ('2017-01-19 01:37', 1, now(), '192.168.2.6', '10.29.78.3', '8.8.4.4', 19, 20, 'Fa0/0');
我现在只是举个例子,用来 使用插入流时的时间生成timeuuid。我也在人工桶中插入了1,在这里你可以插入随机数,范围是0-10。有些人根据负载插入多个随机桶,甚至60个或更多。这完全取决于写得有多重。如果您只是将其设置为每分钟一次,集群中的一组节点将是热的,并且这将切换。拥有热节点通常不是一个好主意

有了卡桑德拉,你就可以马上写下你需要的信息,但你没有这样做 写入或类似操作期间的任何连接。将所需的数据保存在内存中 用您需要的信息标记数据,只需插入即可,无需进行非规范化

此外,您还可以以关系方式对解决方案进行建模,并告知您希望如何进行建模
访问数据,然后我们可以深入了解细节。

我也得出了这个结论,接口数据确实没有那么大(假设每个接口有5000个设备@32个,每小时应达到+/-10MB),并且可以保存在内存中。如果是10MB,它完全是一个内存缓存候选,如果出现问题,可以回退到cassandra:)我不建议gunwant在单个分区中使用10 MB数据的方法,因为从单个分区中获取10 MB数据需要很长时间(几秒钟)。。。但如果它是在撞车后加载的话,一旦我有了ar,它可能就没问题了
create table flow(
    time_with_minute text,
    artificial_bucket int,
    stamp timeuuid,
    host text,
    ip_src text,
    ip_dst text,
    iface_in int,
    iface_out int,
    iface_name text,
    primary key((time_with_minute, artificial_bucket), stamp)
);
insert into flow(time_with_minute, artificial_bucket, stamp, host, ip_src, ip_dst, iface_in, iface_out, iface_name)
    values ('2017-01-19 01:37', 1, now(), '192.168.2.6', '10.29.78.3', '8.8.4.4', 19, 20, 'Fa0/0');