Apache Ignite as an Inter-Microservice Transactional In-Memory Data store

Dishan Metihakwala
May 12, 2020 · 6 min read

For the past few years, hearing the terms “distributed” and “data store” in a single sentence would immediately move my mind to visualize a single word, “Redis”. Now, this was not entirely down to my ignorance. A quick googling would remind you that Redis is still the #1 in the rankings for Key-value stores and ranked #8 out of all DB engines. However, as the proverb goes, there is more than one way to skin a cat. And some of these ways are obviously more equal than others. Behold Apache Ignite.

Apache ignite is an in-memory computing platform that is durable, strongly consistent, and highly available with powerful SQL, key-value, and processing APIs. A comprehensive comparison between Ignite and Redis can be found here. It’s optional support for native persistence is quite advanced compared to the snapshot-based persistence model of Redis. The ability of Ignite to support ACID guaranteed transactions is quite impressive as well. But I was impressed the most by the ANSI-99 compliant, horizontally scalable, and fault-tolerant SQL engine that allows you to interact with Ignite as with a regular SQL database using JDBC, ODBC drivers, or native SQL APIs.

Apache Ignite supports several tech stacks including Java, .Net, C++, Python, JavaScript and PHP. For this article I’m going to use examples from Spring Boot and Java. There are a few ways to use Ignite in the context of a single Spring API. It can be setup as a simple API level cache by configuring the SpringCacheManager, this approach is explored here. Ignite can also be used as the primary durable data store for a service, this approach is explored here. The purpose of this article is to investigate an interesting way to use the power of Ignite to form an inter-microservice, transactional, in-memory data store. To keep things simple, the examples that I explore here are two Spring Boot based REST APIs.

The Menu API is a reference data store which is the source of truth for all menu related data. It stores and manages Items, prices and stock count related information in a mySql database. The requirement here is to keep that data synched with the Order API, which actually validates, accepts and calculates the total for all orders. The Order API has its own mySql database to store the order details. In this design, the items which are managed and stored in by the menu API mySql DB are also stored in an Ignite cache which is shared with the Order API.

The order API will be reducing the available stock count of items as these items are assigned to orders. One caveat here is that the incoming orders do not have the id of the items and hence the Order API needs to query the cache by name to find the matching items. Both APIs have the option of running multiple instances in a typical cloud hosted load balanced manner.

This scenario was chosen to show several different scenarios/patterns on the usage of the ignite cache.

Cache Configuration

Few points to take out if the Ignite cache configuration, this is a cache for the “Item” objects and the atomicity mode is “Transactional”. This indicates that we require full ACID guarantees. The primary index is a long value, which in this case is the item id.

The “Item” entity which is used in the cache has a few special points as well. As the annotations suggest it is designed to be stored in a DB table named “items” (this is indeed done by the menu API) and a few of its fields are annotated with @QuerySqlField. This annotation is a special Ignite annotation which makes these fields visible to Ignite SQL queries. Some of these annotations have @QuerySqlField(index = true) which indicates that these fields are indexed within the ignite cache. I have used Lombok annotations to remove boilerplate code as much as possible. Both the cache configuration and the Item class reside in a separate library which is used by both of the APIs.

Cache Usage patterns

The first usage is a transaction-based cache insert of Item objects, which is performed by the Menu API.

Whenever TRANSACTIONAL atomicity mode is configured, Ignite supports OPTIMISTIC and PESSIMISTIC concurrency modes for transactions. Concurrency mode determines when an entry-level transaction lock should be acquired: at the time of data access or during the prepare phase. Locking prevents concurrent access to an object. Further information about TransactionConcurrency and TransactionIsolation can be found in the Ignite documentation. The main point here is that Ignite provides the user with flexibility on the concurrency and isolation levels of transactions which can be configured to match the performance and behavioral requirements of the specific use case.

In addition to this Ignite provides the capability to execute SQL queries on the same cache, as demonstrated in the code below.

This code demonstrates how the Order API queries the Item cache to find the correct item which matches the item name specified in the order. Notice that the fields annotated with @QuerySqlField can be retrieved and that the name field (which is index in the cache) is used for the WHERE clause. Since this is a read only operation, no transactions are used here. But for update queries you have the option of using transactions.

Another scenario is where a property of an element in the cache is updated via a transaction. In this case, the Order API updates the available stock count of each item in the order in a single transaction. If any of the individual operations fail, the transaction is abandoned.

Conclusions

Ignite integrates well with Java and spring and takes a minimal effort in getting to work. In the example mentioned here, Ignite is running in embedded mode, which means that there is no separate ignite cluster. In fact, the ignite node runs on the same JVM as the spring API which starts it. This removes any network overhead in using the ignite cache. Ignite can also be run as a separate independent cluster. You can optionally use ATOMIC as the CacheAtomicityMode instead of TRANSACTIONAL, this does not provide strong consistency but it often has better performance due to not having to lock the data, and it all depends on your usage scenario. This article is in no way a comprehensive coverage of Apache Ignite as it has several other features such as co-located processing and distributed machine learning acceleration, it merely investigate one potential usage scenario.

Code

Menu API: https://github.com/Dishan006/ignite_menu_api.git

Order API: https://github.com/Dishan006/ignite_order_api.git

Common Lib: https://github.com/Dishan006/ignite_common_lib.git

The Startup

Get smarter at building your thing. Join The Startup’s +787K followers.

Thanks to Lahiru Karunatilake

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Dishan Metihakwala

Written by

Software Architect — SyscoLabs Sri Lanka

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +787K followers.

Dishan Metihakwala

Written by

Software Architect — SyscoLabs Sri Lanka

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +787K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store