I am developing some SPA with a backend written in Java (Spring Boot). In relational DB that backend connects to, there is a table with some dictionary values. Values can edited by users of the app, but it's done really, really rarely (almost never).
Those dictionary values are used in a lot of pages on UI and because of that I would like to "cache" them in a way. What I want to achieve is that I want to load dictionary values on startup to avoid asking DB for values during every request between UI and Backend.
Firstly, I thought about just loading it on the UI part of the app, when user enters the page for the first time. Then I ruled it out, since when one of the users changes the values, it should be reloaded.
What I think might work is just loading them on startup of Backend into some collection (that can be safely used in concurent environment, probably ConcurrentMap) and then during some GET requests asking that collection for the values (instead of DB). When the values are changed, that request just updates the DB table and reloads them into collection.
Then I thought that the collection solution won't be enough, when my backend would be scaled up to more than one instance. In that case, only one of instances will be updated and the second one will provide outdated data. We can avoid it and force refreshes i.e. every 15 minutes (instead of on demand during values update).
But what I think is the best solution is to start some redis service on a side, load dictionary values into it and after every DB update of the values just update the redis instance with the new ones. Every instance of backend would use the same instance of redis, which seems quicker than executing query (select * from _ where _ = _) on DB.
What do you think? Is my thought process is correct? Do you have any ideas that can help solve my issue?
If you are using Spring you could check out Spring Cache Abstraction. That way your cache will be up-to-date whenever some change occurs.
Out of the box few implementations are supported by Spring:
Spring provides a few implementations of that abstraction: JDK java.util.concurrent.ConcurrentMap based caches, Ehcache 2.x, Gemfire cache, Caffeine, and JSR-107 compliant caches (such as Ehcache 3.x). See Plugging-in Different Back-end Caches for more information on plugging in other cache stores and providers.
If you decide to use Memcached implementation you can check out this library (uses Xmemcached under the hood) here.
You could also check a small demo app of how to use Spring Cache Abstraction in your project (link).
I think your in the right path with your approach in terms of 'caching'. I suggest you also check Memcached for it simplicity. Redis is a good choice but still it depends on your requirements and if you need that much feature. just my 2cent
https://aws.amazon.com/elasticache/redis-vs-memcached/
https://devcenter.heroku.com/articles/spring-boot-memcache#add-caching-to-spring-boot
Thanks,
Related
I want to Load Dropdown data from Database at once and set inside java object and tie to my view (JSP page ) and available all the time for that particular controller or functionality using spring mvc AND jsp pages.
I dont want to load on application start up as ours is big one and and each functionality is independent.
It takes a lot of time to start the application if i load on application start up
Is there a way to it using spring mvc pattern and using JSP
Could someone please let me know how to do it
As you have not mentioned how frequently you are doing the database operation or how frequently you are fetching the data. Considering the average user.
Approach: Create your own local cache/ program cache implementation.
Instead of loading all the data from the database during startup, load only master data which will be common for all. If master data is also high then you can perform the lazy loading approach.
Load the data of a specific feature when it is requested for the first time. Keep the data in the local cache.
Whenever someone is making the changes then add the data in the cache and save the same to the database. so you will always have latest data in the cache.
Advantage:
Very useful for common or static master data
-If you need good business logic for some common data. This way only once you are processing the data and keeping cache.
-Fetching the data is very fast as it doesn't involve database request except for the first time
Disadvantage:
If you have a very high number of users and a very high update operation then the updating cache will delay the update process as you need to update it sequentially.
I suggest you can use a combination of approaches to improve the code quality and processing.
This sounds like a typical cache functionality.
Spring supports caching out of the box by #EnableCaching on application level and #Cacheable(“cachename”) on the repository method retrieving your dropdown data. In your simple use case you not even need an additional framework as there is a CacheManager based on ConcurrentHashMap which simply caches for ever.
With caching in place your controller can simply fetch the dropdown data from the repository. Caching will ensure only the first call will really fetch from database and keeps the result in memory for all upcoming calls.
If you ever need more sophisticated caching you only have to exchange the cache manager and configure the cache for your needs.
Correct me if I'm wrong, but from my understanding, "database caches" are usually implemented with an in-memory database that is local to the web server (same machine as the web server). Also, these "database caches" store the actual results of queries. I have also read up on the multiple caching strategies like - Cache Aside, Read Through, Write Through, Write Behind, Write Around.
For some context, the Write Through strategy looks like this:
and the Cache Aside strategy looks like this:
I believe that the "Application" refers to a backend server with a REST API.
My first question is, in the Write Through strategy (application writes to cache, cache then writes to database), how does this work? From my understanding, the most commonly used database caches are Redis or Memcached - which are just key-value stores. Suppose you have a relational database as the main database, how are these key-value stores going to write back to the relational database? Do these strategies only apply if your main database is also a key-value store?
In a Write Through (or Read Through) strategy, the cache sits in between the application and the database. How does that even work? How do you get the cache to talk to the database server? From my understanding, the web server (the application) is always the one facilitating the communication between the cache and the main database - which is basically a Cache Aside strategy. Unless Redis has some kind of functionality that allows it to talk to another database, I don't quite understand how this works.
Isn't it possible to mix and match caching strategies? From how I see it, Cache Aside and Read Through are caching strategies for application reads (user wants to read data), while Write Through and Write Behind are caching strategies for application writes (user wants to write data). Couldn't you have a strategy that uses both Cache Aside and Write Through? Why do most articles always seem to portray them as independent strategies?
What happens if you have a cluster of webs servers? Do they each have their own local in-memory database that acts as a cache?
Could you implement a cache using a normal (not in-memory) database? I suppose this would still be somewhat useful since you do not need to make an additional network hop to the database server (since the cache lives on the same machine as the web server)?
Introduction & clarification
I guess you have one misunderstood point, that the cache is NOT expclicitely stored on the same server as the werbserver. Sometimes, not even the database is sperated on it's own server from the webserver. If you think of APIs, like HTTP REST APIs, you can use caching to not spend too many resources on database connections & queries. Generally, you want to use as few database connections & queries as possible. Now imagine the following setting:
You have a werbserver who serves your application and a REST API, which is used by the webserver to work with some resources. Those resources come from a database (lets say a relational database) which is also stored on the same server. Now there is one endpoint which serves e.g. a list of posts (like blog-posts). Every user can fetch all posts (to make it simple in this example). Now we have a case where one can say that this API request could be cached, to not let all users always trigger the database, just to query the same resources (via the REST API) over and over again. Here comes caching. Redis is one of many tools which can be used for caching. Since redis is a simple in-memory key-value storage, you can just put all of your posts (remember the REST API) after the first DB-query, into the cache. All future requests for the posts-list would first check whether the posts are alreay cached or not. If they are, the API will return the cache-content for this specific request.
This is one simple example to show off, what caching can be used for.
Answers on your question
My first question is, why would you ever write to a cache?
To reduce the amount of database connections and queries.
how is writing to these key-value stores going to help with updating the relational database?
It does not help you with updating, but instead it helps you with spending less resources. It also helps you in terms of "temporary backing up" some data - but that only as a very little side effect. For this, out there are more attractive solutions (Since redis is also not persistent by default. But it supports persistence.)
Do these cache writing strategies only apply if your main database is also a key-value store?
No, it is not important which database you use. Whether it's a NoSQL or SQL DB. It strongly depends on what you want to cache and how the database and it's tables are set up. Do you have frequent changes in your recources? Do resources get updated manually or only on user-initiated actions? Those are questions, leading you to the right caching implementation.
Isn't it possible to mix and match caching strategies?
I am not an expert at caching strategies, but let me try:
I guess it is possible but it also, highly depends on what you are doing in your DB and what kind of application you have. I guess if you find out what kind of application you are building up, then you will know, what strategy you have to use - i guess it is also not recommended to mix those strategies up, because those strategies are coupled to your application type - in other words: It will not work out pretty well.
What happens if you have a cluster of webs servers? Do they each have their own local in-memory database that acts as a cache?
I guess that both is possible. Usually you have one database, maybe clustered or synchronized with copies, to which your webservers (e.g. REST APIs) make their requests. Then whether each of you API servers would have it's own cache, to not query the database at all (in cloud-based applications your database is also maybe on another separated server - so another "hop" in terms of networking). OR (what i also can imagine) you have another middleware between your APIs (clusterd up) and your DB (maybe also clustered up) - but i guess that no one would do that because of the network traffic. It would result in a higher response-time, what you usually want to prevent.
Could you implement a cache using a normal (not in-memory) database?
Yes you could, but it would be way slower. A machine can access in-memory data faster then building up another (local) connection to a database and query your cached entries. Also, because your database has to write the entries into files on your machine, to persist the data.
Conclusion
All in all, it is all about being fast in terms of response times and to prevent much network traffic. I hope that i could help you out a little bit.
Using the Mendix Business Modeler to build web-applications is fundamentally different than developing web-applications using technologies like Java/Spring/JSF. But, I'm going to try to compare the two for the sake of this question:
In a Java/Spring based application, I can integrate my application with the 3rd party product Ehcache to cache data at the method level. For example, I can configure ehcache to store the return value for a given method (with a specific time-to-live). Whenever this method is called, ecache will automatically check if the method has been called previously with the same parameters and if there is a stored return value in the cache. If so, the method is never actually executed and instead the cached method return value is immediately returned.
I would like to have the same capabilities within Mendix, but in this case I would be caching Microflow return values. Also, I don't want to be forced to add actions all over the place explicitly telling the Microflow to check the cache. I would like to register my Microflows for caching in one centralized place, or simply flag each Microflow for being cached. In other words, this question is just as much about the concept of aspect-oriented-programming (AOP) in Mendix as it is about caching: is there a way to get hooks into Microflow invocation so I can apply pre and post execution operations? In my opinion the same reasons why AOP has it's place an purpose in Java exist in Mendix.
When working with the Mendix application it tries to do as much for you as possible, in this case that means that the platform already has an object cache to keep all objects that need caching.
Internally the Mendix platform uses Ehcache to do that.
However it is not really possible to influence that cache as you would normally do in Java/Spring.This is due to all the functionality of the Mendix Platform, that already tries to cache all objects as efficiently as possible.
Every object you create is always added to the cache. When working with that object it stays in cache until the Platform detects that the specific object can no longer be accessed either through the UI or a microflow.
There are also API calls available that instruct the platform to retain the object in cache regardless of it's usage. But that doesn't provide you with the flexibility as you asked for.
But specifically on your question, my initial response would be: Why would you want to cache a microflow output?
Objects are already cached in memory, and the browser client only refreshes the cache when instructed. Any objects that you are using will be cached.
Also when looking at most of the microflows that we use, I don't think it is likely that I would want to cache the output instead of re-running the microflows. Due to the design of the majority of the microflows I think it is likely that most microflows can return a slightly different output every time you execute it.
There are many listener classes you can subscribe to in the Mendix platform that allow you to trigger something in addition to the default action. But that would require some detailed knowledge of the current behavior.
For example you can override the login action, but if you don't perform all the correct validations you could make the login process less secure.
I have Oracle as my main RDBMS for read and write, but I want to use couchbase as caching layer as it has map-reduce as can be used as memcache. Any idea as to how i can implement that, and how to transfer and update data in the caching layer, when Oracle is updated or inserted etc.
You are not telling anything about your current performance issues.
I have seen too many applications which do not really take advantage of RDBMS/SQL features, especially if an ORM sits in between.
The cure is to put another cache on top of a database, and to synchronize this in a cluster manually using IP multicasts (SwarmCache for example), message queues (JMS) or nightly import jobs. It could create more problems in the end. And it increases system complexity.
So my answer to your question is: I would not do it, as long as there is room for improvement regarding your data model and/or queries.
I believe your question is about Database synchronization. This can be done through a combination of using DB dependencies and "right-thru" features that I am not too sure about whether couchbase offers. So with DB dependency you have cached items dependent upon Db items and if the DB items are updated or deleted the corresponding dependent item in the cache is removed and at the same time you can write a "right-thru" handler executed at the server level; and the main purpose of this handler is loading fresh copies of the removed items in the cache. So, basically, you'll write the handler once and registerit with the cache server and the cache server will execute it when needed to sync. new items in the DB with the cache. This reading on Db synchronization can be useful . Its based on a product Ncache.
So your question is not directly related to Couchbase, but as other stated more about how you can be alerted when data are changing into your Oracle instance.
One thing that is not well known is the Oracle Database Change Notification feature that is quite cool for this:
http://docs.oracle.com/cd/E11882_01/java.112/e16548/dbchgnf.htm
So you can create an application that is listening to your changes and pushes the data into Couchbase.
I have a series of code books in my database, and I am using plain JDBC calls to fetch them and store them in a collection. I would like to put these in some kind of a cache at application startup time in order to save time later.
I don't need any fancy stuff like automatic object invalidation, TTL etc - the code books change rarely, so I'll trigger the update myself and just reload the whole cache when the need arises.
The project where I need this uses Spring, and this is my first project using it. Is there a standard/elegant way to do this in Spring?
Thanks.
Check out Spring-cache.
Supports EHCache, OSCache and a memory cache, but allows pluggable cache providers too.