We have a Cassandra Cluster with 3 pods, in Google Cloud Kubernetes. Our Cassandra version is 3.9 we are using the Google images.
I got a problem when I tried to create a Materialized View from a table.
The schema of the table is like:
CREATE TABLE environmental_data (
block_id int,
timestamp timestamp,
device_id int,
sensor_id int,
.
.
.
PRIMARY KEY (block_id, timestamp, device_id, sensor_id)
I want to create a view with the device_id as cluster key, I tried to do this:
CREATE MATERIALIZED VIEW environmental_data_by_device AS
SELECT block_id, timestamp, device_id, sensor_id,... FROM environmental_data
WHERE block_id is not null
and timestamp is not null
and device_id is not null
and sensor_id is not null
PRIMARY KEY ((device_id), timestamp, sensor_id, block_id)
WITH CLUSTERING ORDER BY (timestamp DESC);
In local with a very small amount of data, everything went well. But in production with 80 million lines, 2 pods crashed, and Cassandra looped on this error:
Unknown exception caught while attempting to update MaterializedView! environmental_data
java.lang.IllegalArgumentException: Mutation of XXXX bytes is too large for the maximum size of XXXX
There was also many java.lang.OutOfMemoryError: Java heap space
What can I do to be sure the next try will be successful? To put down the production Cassandra a second time is not really conceivable.
I already succeed to create a view base on a table but it was not that big.
According to docs, Cassandra considers updates within the same partition as a single mutation. In your case, I suppose, this means that every new insert with the same device id may result in transferring all the data that was previously written into that partition. To avoid it, you should consider splitting the data in the mat. view into smaller pieces using the partition key. For example you may introduce minute or hour wide timebuckets depending on the measurement frequency.
I can give you some hints from the infrastructure point of view since I do not know Cassandra in deep. If I were in charge of the infrastructure I would check that the you have set up in the proper way the Deployments to make sure since you had many java.lang.OutOfMemoryError
that:
This is often not highlighted but can be an issue: if you have 3 nodes having 3 GB of RAM
and 2 pods consuming 2 GB
with no memory request it might happen that they are scheduled on the very same node being killed after a while. Setting up the memory request everything goes fine.
Moreover you can find here and interesting article that touches also Java Heap Memory Based AutoScaling in Kubernetes.
You can check how much memory and CPU the pods are consuming through the following command:
$ kubectl top pods --namespace=xxxx
And if the nodes are suffering
$ kubectl top nodes