<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cassandra on Random Ramblings</title><link>https://blog.foundev.pro/tags/cassandra.html</link><description>Recent content in Cassandra on Random Ramblings</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Tue, 23 Feb 2021 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.foundev.pro/tags/cassandra/index.xml" rel="self" type="application/rss+xml"/><item><title>Getting the DataStax cass-operator working on Mac</title><link>https://blog.foundev.pro/2021/02/23/kubernetes-cassandra-local-workstation.html</link><pubDate>Tue, 23 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.foundev.pro/2021/02/23/kubernetes-cassandra-local-workstation.html</guid><description>&lt;h1&gt;Getting the DataStax cass-operator working on Mac&lt;/h1&gt;&#10;&lt;p&gt;Just leaving this here for anyone coming back to this later. This works as of Feb 23 2021 on Big Sur&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;install docker desktop &lt;a href="https://www.docker.com/products/docker-desktop"&gt;https://www.docker.com/products/docker-desktop&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;install k3d &lt;a href="https://github.com/rancher/k3d#get"&gt;https://github.com/rancher/k3d#get&lt;/a&gt; you can just run &lt;code&gt;curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;create cluster: &lt;code&gt;k3d cluster create&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;install operator manifest &lt;code&gt;kubectl create -f https://raw.githubusercontent.com/datastax/cass-operator/v1.5.1/docs/user/cass-operator-manifests-v1.19.yaml&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;download a cassandra data center yaml &lt;code&gt;curl -O https://gist.githubusercontent.com/rsds143/0e9263ed4287d888fab36eb3e4aec502/raw/f919172c64452a2277b7523d680a9e12916d0d39/cassandra-dc.yaml&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;run &lt;code&gt;kubectl create -f cassandra-dc.yaml --namespace cass-operator&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;wait for cassandra to come up &lt;code&gt;kubectl logs cluster1-dc1-default-sts-0 --namespace cass-operator server-system-logger&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;get username &lt;code&gt;export CQLUSER=$(kubectl get secret cluster1-superuser -o json -n cass-operator | grep \&amp;quot;username\&amp;quot; | sed -E 's/\&amp;quot;(.+)\&amp;quot;: \&amp;quot;(.+)\&amp;quot;/\2/' | base64 -d)&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;get password &lt;code&gt;export CQLPASS=$(kubectl get secret cluster1-superuser -o json -n cass-operator | grep \&amp;quot;password\&amp;quot; | sed -E 's/\&amp;quot;(.+)\&amp;quot;: \&amp;quot;(.+)\&amp;quot;/\2/' | sed -E 's/,*$//g' | base64 -d )&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;log into cqlsh &lt;code&gt;kubectl exec -it -n cass-operator cluster1-dc1-default-sts-0 -- cqlsh -u $CQLUSER -p $CQLPASS&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;enjoy your cassandra cluster&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;The yaml I have linked too above is here&lt;/p&gt;</description></item><item><title>Apache NiFi and Cassandra</title><link>https://blog.foundev.pro/2021/02/08/apache-nifi-cassandra-sprocs.html</link><pubDate>Mon, 08 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.foundev.pro/2021/02/08/apache-nifi-cassandra-sprocs.html</guid><description>&lt;h1&gt;Apache NiFi and Cassandra&lt;/h1&gt;&#10;&lt;p&gt;Looked at Apache NiFi for the first time in a long time as someone didn&amp;rsquo;t know if it had support for stored procedures or not. I looked up the latest source&#10;and sure enough I see no stored procedures used for any of the statements. Looking at the &lt;a href="https://github.com/apache/nifi/blob/953327cdf587c6b68765c0d32508873d8a0031e7/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/main/java/org/apache/nifi/processors/cassandra/PutCassandraRecord.java"&gt;PutCassandraRecord.java&lt;/a&gt; I see inserts and updates are just statements that are never prepared:&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; query = generateInsert(cassandraTable, schema, recordContentMap);&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;and&lt;/p&gt;</description></item><item><title>Heap Size Around 32 GB</title><link>https://blog.foundev.pro/2021/02/03/heap-size-around-31gb.html</link><pubDate>Wed, 03 Feb 2021 00:00:00 +0000</pubDate><guid>https://blog.foundev.pro/2021/02/03/heap-size-around-31gb.html</guid><description>&lt;h1&gt;Heap Size Around 32 GB&lt;/h1&gt;&#10;note: originally written Feb 3 2021&#10;&lt;p&gt;There was a question this morning around a pretty common discussion point around 31 gb versus 32 gb of heap. This &lt;a href="http://java-performance.info/over-32g-heap-java/"&gt;article discusses this in more detail&lt;/a&gt;, the key point follows:&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;Be careful when you increase your application heap size over 32G (from under 32G to over 32G) – JVM switches to 64 bit object references at that moment, which means that your application may end up with less available heap space. A rule of thumb is to jump from 32G right to 37-38G and continue adding memory from that point. The actual area of “grey” territory depends on your application – the bigger an average Java object in your application, the smaller is the overhead.&lt;/p&gt;</description></item><item><title>Starting Cassandra - Data modeling in the brief</title><link>https://blog.foundev.pro/2020/02/05/getting-started-cassandra-part-3.html</link><pubDate>Wed, 05 Feb 2020 00:00:00 +0000</pubDate><guid>https://blog.foundev.pro/2020/02/05/getting-started-cassandra-part-3.html</guid><description>&lt;h1&gt;Starting Cassandra - Data modeling in the brief&lt;/h1&gt;&#10;&lt;p&gt;Cassandra data modeling isn&amp;rsquo;t really something you can do &amp;ldquo;in the brief&amp;rdquo; and is itself a subject that can take years to fully grasp, but this should be a good starting point.&lt;/p&gt;&#10;&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;&#10;&lt;p&gt;Cassandra distributes data around the cluster via the &lt;em&gt;partition&lt;/em&gt; &lt;em&gt;key&lt;/em&gt;.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#cf222e"&gt;CREATE&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;TABLE&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;my_key&lt;span style="color:#1f2328"&gt;.&lt;/span&gt;my_table_by_postal_code&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#1f2328"&gt;(&lt;/span&gt;postal_code&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#6639ba"&gt;text&lt;/span&gt;&lt;span style="color:#1f2328"&gt;,&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;id&lt;span style="color:#fff"&gt; &lt;/span&gt;uuid&lt;span style="color:#1f2328"&gt;,&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;balance&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#6639ba"&gt;float&lt;/span&gt;&lt;span style="color:#1f2328"&gt;,&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;PRIMARY&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;KEY&lt;/span&gt;&lt;span style="color:#1f2328"&gt;(&lt;/span&gt;postal_code&lt;span style="color:#1f2328"&gt;,&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;id&lt;span style="color:#1f2328"&gt;));&lt;/span&gt;&lt;span style="color:#fff"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above table the &lt;em&gt;partition&lt;/em&gt; &lt;em&gt;key&lt;/em&gt; is &lt;code&gt;postal_code&lt;/code&gt; and the &lt;em&gt;clustering&lt;/em&gt; &lt;em&gt;column&lt;/em&gt; is&lt;code&gt;id&lt;/code&gt;. The &lt;em&gt;partition&lt;/em&gt; &lt;em&gt;key&lt;/em&gt; will locate the data on the cluster for us. The clustering column allows us multiple rows per &lt;em&gt;partition&lt;/em&gt; &lt;em&gt;key&lt;/em&gt; so that we can filter how much data we read per partition.&#10;The &amp;lsquo;optimal&amp;rsquo; query is one that retrieves data from only one node and not so much data that GC pressure or latency issues result. The following query is breaking that rule and retrieving 2 partitions at once via the IN parameter.&lt;/p&gt;</description></item><item><title>Starting Cassandra - Load testing Cassandra in brief</title><link>https://blog.foundev.pro/2020/02/04/getting-started-cassandra-part-2.html</link><pubDate>Tue, 04 Feb 2020 00:00:00 +0000</pubDate><guid>https://blog.foundev.pro/2020/02/04/getting-started-cassandra-part-2.html</guid><description>&lt;h1&gt;Starting Cassandra - Load testing Cassandra in brief&lt;/h1&gt;&#10;&lt;p&gt;An opinionated guide on the &amp;ldquo;correct&amp;rdquo; way to load test Cassandra. I&amp;rsquo;m aiming to keep this short so I&amp;rsquo;m going to leave out a &lt;em&gt;lot&lt;/em&gt; of the nuance that one would normally get into when talking about load testing cassandra.&lt;/p&gt;&#10;&lt;h2 id="if-you-have-no-data-model-in-mind"&gt;If you have no data model in mind&lt;/h2&gt;&#10;&lt;p&gt;Use cassandra stress since it&amp;rsquo;s around:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;first initialize the keyspace with RF3 &lt;code&gt;cassandra-stress &amp;quot;write cl=ONE no-warmup -col size=FIXED(15000) -schema replication(strategy=SimpleStrategy,factor=3)&amp;quot;&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;second run stress &lt;code&gt;cassandra-stress &amp;quot;mixed n=1000k cl=ONE -col size=FIXED(15000)&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;repeat as often as you&amp;rsquo;d like with as many clients as you want.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="if-you-have-a-specific-data-model-in-mind"&gt;If you have a specific data model in mind&lt;/h2&gt;&#10;&lt;p&gt;You can use cassandra-stress, but I suspect you&amp;rsquo;re going to find your data model isn&amp;rsquo;t supported (collections for example) or that you don&amp;rsquo;t have the required PHD to make it work the way you want. There are probably 2 dozen options from here you can use to build your load test, some of the more popular ones are gatling, jmeter, and tlp-stress. My personal favorite for this though, write a small simple python or java program that replicates your use case accurately in your own code, using a faker library to generate your data. This takes more time but you tend to have less surprises in production as it will accurately model your code.&lt;/p&gt;</description></item><item><title>Starting Cassandra - Setting up a Multi-DC environment</title><link>https://blog.foundev.pro/2020/02/03/getting-started-cassandra-part1.html</link><pubDate>Mon, 03 Feb 2020 00:00:00 +0000</pubDate><guid>https://blog.foundev.pro/2020/02/03/getting-started-cassandra-part1.html</guid><description>&lt;h1&gt;Starting Cassandra - Setting up a Multi-DC environment&lt;/h1&gt;&#10;&lt;p&gt;This is a quick and dirty opinionated guide to setting up a Cassandra cluster with multiple data centers.&lt;/p&gt;&#10;&lt;h2 id="a-new-cluster"&gt;A new cluster&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;In cassandra.yaml set &lt;code&gt;endpoint_snitch: GossipingPropertyFileSnitch&lt;/code&gt;, some prefer PropertyFileSnitch for the ease of pushing out one file. GossipingPropertyFileSnitch is harder to get wrong in my experience.&lt;/li&gt;&#10;&lt;li&gt;set dc in cassandra-rackdc.properties. Set to be whatever dc you want that node to be in. Ignore rack until you really need it, 8/10 people that use racks do it wrong the first time, and it&amp;rsquo;s slightly painful to unwind.&lt;/li&gt;&#10;&lt;li&gt;finish adding all of your nodes.&lt;/li&gt;&#10;&lt;li&gt;if using authentication, set &lt;code&gt;system_auth&lt;/code&gt; keyspace to use NetworkTopologyStrategy in cqlsh with RF 3 (or == number of replicas if less than 3 per dc) for each datacenter you&amp;rsquo;ve created &lt;code&gt;ALTER KEYSPACE system_auth WITH REPLICATION= {'class' : 'NetworkTopologyStrategy', 'data_center_name' : 3, 'data_center_name' : 3};&lt;/code&gt;, run repair after changing RF&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;nodetool repair -pr system_auth&lt;/code&gt; on each node in the cluster on the new keyspace.&lt;/li&gt;&#10;&lt;li&gt;create your new keyspaces for your app with RF 3 in each dc (much like you did for the &lt;code&gt;system_auth&lt;/code&gt; step above).&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;nodetool repair -pr whatever_new_keyspace&lt;/code&gt; on each node in the cluster on the new keyspace.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="an-existing-cluster"&gt;An existing cluster&lt;/h2&gt;&#10;&lt;p&gt;This is harder and involves more work and more options, but I&amp;rsquo;m going to discuss the way that gets you into the least amount of trouble operationally.&lt;/p&gt;</description></item><item><title>Snakeyaml error handling is tough</title><link>https://blog.foundev.pro/2019/12/27/snakeyaml-perms.html</link><pubDate>Fri, 27 Dec 2019 09:30:00 -0600</pubDate><guid>https://blog.foundev.pro/2019/12/27/snakeyaml-perms.html</guid><description>&lt;h1&gt;"Snakeyaml error handling is tough"&lt;/h1&gt;&#10;&lt;p&gt;Cassandra for years has relied on snakeyaml to parse configuration files, and it does a fine job, really not a lot of complaints. Until one day a colleague of mine discovered an issue where a permission issue incorrectly reported as an invalid yaml file (complete with the supposedly offending key). Digging into the source code and trying to match up the message. I found that &lt;a href="https://github.com/apache/cassandra/blob/06209037ea56b5a2a49615a99f1542d6ea1b2947/src/java/org/apache/cassandra/config/YamlConfigurationLoader.java#L128"&gt;we were handling YAMLException&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Cassandra - Batch Loading Without the Batch The Nuanced Edition</title><link>https://blog.foundev.pro/2016/04/29/cassandra-batch-loading-without-the-batch-the-nuanced-edition.html</link><pubDate>Fri, 29 Apr 2016 16:03:56 +0000</pubDate><guid>https://blog.foundev.pro/2016/04/29/cassandra-batch-loading-without-the-batch-the-nuanced-edition.html</guid><description>&lt;h1&gt;Cassandra - Batch Loading Without the Batch The Nuanced Edition&lt;/h1&gt;&#10; My [previous post on this subject](https://blog.foundev.pro/2014/08/28/cassandra-batch-loading-without-the-batch-keyword.html) has proven extraordinarily popular and I get commentary on it all the time, most of it quite good. It has however, gotten a decent number of comments from people quibbling with the nuance of the post and pointing out it’s failings, which is fair because I didn’t explicitly spell this out as a “framework of thinking” blog post or a series of principles to consider. This is the tension between making something approachable and understandable to the new user but still technically correct for the advanced one. Because of where Cassandra was at the time and the user base I was encountering day to day, I took the approach of simplification for the sake of understanding. However, now I think is a good time to write this up with all the complexity and detail of a production implementation and the tradeoffs to consider.&#10;&lt;h3 id="tldr"&gt;&lt;em&gt;TLDR&lt;/em&gt;&lt;/h3&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;em&gt;Find the ideal write size it can make a 10x difference in perf (10k-100k is common).&lt;/em&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;em&gt;Limit threads in flight when writing.&lt;/em&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;em&gt;Use tokenaware unlogged batches if you need to get to your ideal size.&lt;/em&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;&lt;em&gt;Details on all this below.&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Spark job that writes to Cassandra just hangs when one node goes down?</title><link>https://blog.foundev.pro/2016/04/05/spark-job-that-writes-to-cassandra-just-hangs-when-one-node-goes-down.html</link><pubDate>Tue, 05 Apr 2016 00:00:00 +0000</pubDate><guid>https://blog.foundev.pro/2016/04/05/spark-job-that-writes-to-cassandra-just-hangs-when-one-node-goes-down.html</guid><description>&lt;h1&gt;Spark job that writes to Cassandra just hangs when one node goes down?&lt;/h1&gt;&#10;### &lt;span style="font-size: 16px;"&gt;So this was hyper obvious once I saw the executor logs and the database schema, but this had me befuddled at first and the change in behavior with one node should have made it obvious.&lt;/span&gt; {#23da}&#10;&lt;p id="f2c8"&gt;&#10; The code was simple, read a bunch of information, do some minor transformations and flush to Cassandra. This was nothing crazy. But during the users fault tolerance testing, the job would just seamingly hang indefinitely when a node was down.&#10;&lt;/p&gt;</description></item><item><title>Cassandra Query Patterns: Not using the “in” query for multiple partitions.</title><link>https://blog.foundev.pro/2014/09/22/cassandra-query-patterns-not-using-the-in-query-for-multiple-partitions.html</link><pubDate>Mon, 22 Sep 2014 22:12:58 +0000</pubDate><guid>https://blog.foundev.pro/2014/09/22/cassandra-query-patterns-not-using-the-in-query-for-multiple-partitions.html</guid><description>&lt;h1&gt;Cassandra Query Patterns: Not using the “in” query for multiple partitions.&lt;/h1&gt;&#10;So lets say you’re doing you’re best to data model all around one partition. You’ve done your homework and all you queries look like this:&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#f7f7f7;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;SELECT&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0550ae"&gt;*&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;FROM&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;my_keyspace&lt;span style="color:#1f2328"&gt;.&lt;/span&gt;users&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#cf222e"&gt;where&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;id&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0550ae"&gt;=&lt;/span&gt;&lt;span style="color:#fff"&gt; &lt;/span&gt;&lt;span style="color:#0550ae"&gt;1&lt;/span&gt;&lt;span style="color:#fff"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Over time as features are added however, you make some tradeoffs and need to start doing queries across partitions. At first there are only a few queries like this.&lt;/p&gt;</description></item><item><title>Cassandra - Batch loading without the Batch keyword</title><link>https://blog.foundev.pro/2014/08/28/cassandra-batch-loading-without-the-batch-keyword.html</link><pubDate>Thu, 28 Aug 2014 13:10:55 +0000</pubDate><guid>https://blog.foundev.pro/2014/08/28/cassandra-batch-loading-without-the-batch-keyword.html</guid><description>&lt;h1&gt;Cassandra - Batch loading without the Batch keyword&lt;/h1&gt;&#10;ATTENTION:&#10;&lt;p&gt;&lt;em&gt;This post is intentionally simplistic to help explain tradeoffs that need to be made. If you are looking for some production level nuance go &lt;a href="https://blog.foundev.pro/2016/04/29/cassandra-batch-loading-without-the-batch-the-nuanced-edition.html"&gt;read this afterwords.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;Batches in Cassandra are often mistaken as a performance optimization. They can be but only in rare cases. First we need to discuss the different types of batches:&lt;/p&gt;&#10;&lt;h2 id="unlogged-batch"&gt;Unlogged Batch&lt;/h2&gt;&#10;&lt;p&gt;A good example of an unlogged batch follows and assumes a partition key of date. The following batch is effectively one insert because all inserts are sharing the same partition key. Assuming a partition key of date the above batch will only resolve to one write internally, no matter how many there are as long as they have the same date value. This is therefore the primary use case of an unlogged batch:&lt;/p&gt;</description></item></channel></rss>