用过Nosql的人都知道,主键设计有2个方面考量。一是满足查询,二是避免热点。Cassandra自然也不例外。下面我们拿一些常见的事例来探讨下这个问题。在电信行业,许多运营商用Cassandra来存储用户的通话记录或者短信收发记录,因为一个上亿人口的大省,平均每个用户一天100条记录就将产生100亿条,高峰期每秒的并发量可能是百万级别。其中一个常见查询就是根据手机号ID查询一段时间内的记录,指定某一条记录进行查询。我们来设计个表来看看是不是很好的满足需求。=
CREATE TABLE call_record(
phone_number text,
record_time timestamp,
from_who text,
to_whoo text,
........//其它字段略去
PRIMARY KEY (phone_number, record_time)
)WITH CLUSTERING ORDER BY(record_time desc)
这样看上去似乎不会有问题,一般一个用户一天100条记录,一年3万多条,然后按phone_number为分区键,已经足够离散了。但是市面上总是会有一些非法分子使用“呼死你”去骚扰一个用户,或者是内部有个定时拨测的账户,每隔10秒呼叫一次,一天可能就超过8640条,一年超过300万条记录。Cassandra 每个分区的限制数是20亿,经验法则Cassandra 中的最大分区大小应小于100MB ,理想情况下小于 10MB。 假设一条记录是50字节,300万条记录就是150MB了。这个明显会给系统带来比较重的负担。所以为了解决这个问题,应该考虑缩小分区的数量,比如这样设计:
CREATE TABLE call_record(
phone_number text,
month text,//月份
record_time timestamp,
from_who text,
to_whoo text,
........//其它字段略去
PRIMARY KEY ((phone_number, month),record_time)
)WITH CLUSTERING ORDER BY(record_time desc)
这种时间序的场景,考虑增加一个月份作为主键的复合键,查询到时候增加指定月份进行查询,这样把分区数量再打散,极端情况下分配到每个分区的最大值就不会超过12.5MB了。
想学习更多的Casssandra、Spark相关知识,请扫码关注Datastax微信公众