I'm going to deploy an in-memory cache cluster (current thinking Redis) for some public facing web workloads and was wondering where the cluster should live (deployment topology), two options IMO:
Sitting on the Web tier (which is horizontally scalable)
Create a dedicated cache cluster behind the Web Tier and in-front of the DB Tier.
Background, application on Web and DB Tier running on Windows, so if I stick the cluster on the Web Tier then it needs to be supported on Windows (MSFT have a stable Redis port), if I go with the dedicated cache tier I was thinking of some lightweight Linux servers (HA cluster) meaning as the Web Tier horizontally scaled it used this cache cluster for its lookups e.g. reference data etc.
Pros, cons thoughts, other option I'm missing?
*Note, I don't have the luxury of utilising a cloud service provider "cache as a service", not an option unfortunately ...
Cheers,
Surprised at the lack of community support around Redis and caching in general.
To answer my question, I ended up going with a Linux (RHEL) master/slave Redis cache tier, opted for master/slave deployment topology giving me HA at the cache tier (as opposed to a Redis cache cluster). Master gives me writes, master/slave allows for reads. Suits my needs as I will go to the DB on a cache miss, configured Redis to never persist to disk (in-memory only).
Related
I am after a scalable & fast restartable caching solution which has a provision to boot up quickly (E.g. storing the cache on disk during application shut down (or while running) and restoring it back while application comes up) and can maintain a few GB size of cache. (Our cache is not a distributed cache)
Enterprise ehcache/BigMemory Go (http://ww1.terracotta.org/documentation/3.7.4/bigmemorygo/configuration/fast-restart) supports this feature but they are licensed.
Any other suggestions are also welcome. I dont want to use Gemfire or Geode as they need different infra to maintain.
What are the pros and cons for JCS against Ignite?
In Apache Ignite, the server node(where caches are stored) can run in a separate JVM in a separate host machine, other than the client application. For example, our application can be distributed in 4 nodes, and the distributed cache can be spread across 10 separate independent nodes. Can JCS Cache support this scenario?
From the docs, I understand the JCS Cache supports distributed caching, but does the cache reside in the same JVM process as the Client application or it can be a separate one like in Ignite.
These are two different projects. JCS is just a local in-memory cache which is designed to be mostly read-only. Each local cache can have lateral TCP cache that will notify other cache instances whenever local cache is updated, but this does not have any consistency guarantees, and there is no partitioning. Ignite on the other head is Data Grid (actually even more), it can run on a separate cluster, partition the data across nodes and guarantee update consistency so that you interact with the cluster as with a single entity, regardless of how many nodes you have.
Having said that, based on your use case description I think Ignite is more suitable.
If we implement the caching server using Infinispan, what are the possible client APIs to choose? Is Java Hot Rod client a good choice? Any other solutions?
Thank you!
As usually - Depends on your needs.
When you use HotRod you use Infinispan in a fashion similar to using MySQL/Sybase - you have an application that connects to the database backend which means
dedicated servers need to be set up and maintained
need to have multiple (dedicated) boxes to have high-availability and resiliency
but
HotRod client does some load-balancing for you
you can have dedicated data store servers with very specific configuration/separation/etc.
this mode is useful when Infinispan is used as a distributed store with database persistence
You might also use Infinispan in embedded mode, when you data is shared between you applications containing Infinispan instances; this mode is like having a HashMap that is
synchronized across the network with other boxes:
this gives you HA/resiliency by default (if your application is deployed with 2+ instances)
no need to have separate servers (no separate maintenance)
every new instance of your app will also contribute to the Infinispan cluster increasing HA/resiliency
(for testing you'll probably use Infinispan in embedded mode, anyway)
If you have your applications running on the same network segment (no firewall/switches/etc.) it might be easier just to use
Infinispan embedded mode, as it's easy to set up with lot of examples.
My recommendation would be to have a cache layer in your code that separates cache operations w/o the implementation so you can use whatever cache provider you want to use.
For Infininispan you should read the Infinispan User's Guide as #Galder pointed out.
The server modules documentation clarifies this.
For the first time I am developing an app that requires quite a bit of scaling, I have never had an application need to run on multiple instances before.
How is this normally achieved? Do I cluster SQL servers then mirror the programming across all servers and use load balancing?
Or do I separate out the functionality to run some on one server some on another?
Also how do I push out code to all my EC2 windows instances?
This will depend on the requirements you have. But as a general guideline (I am assuming a website) I would separate db, webserver, caching server etc to different instance(s) and use s3(+cloudfont) for static assets. I would also make sure that some proper rate limiting is in place so that only legitimate load is on the infrastructure.
For RDBMS server I might setup a master-slave db setup (RDS makes this easier), use db sharding etc. DB cluster solutions also exists which will be more complex to setup but simplifies database access for the application programmer. I would also check all the db queries and the tune db/sql queries accordingly. In some cases pure NoSQL type databases might be better than RDBMS or a mix of both where the application switches between them depending on the data required.
For webserver I will setup a loadbalancer and then use autoscaling on the webserver instance(s) behind the loadbalancer. Something similar will apply for app server if any. I will also tune the web servers settings.
Caching server will also be separated into its on cluster of instance(s). ElastiCache seems like a nice service. Redis has comparable performance to memcache but has more features(like lists, sets etc) which might come in handy when scaling.
Disclaimer - I'm not going to mention any Windows specifics because I have always worked on Unix machines. These guidelines are fairly generic.
This is a subjective question and everyone would tailor one's own system in a unique style. Here are a few guidelines I follow.
If it's a web application, separate the presentation (front-end), middleware (APIs) and database layers. A sliced architecture scales the best as compared to a monolithic application.
Database - Amazon provides excellent and highly available services (unless you are on us-east availability zone) for SQL and NoSQL data stores. You might want to check out RDS for Relational databases and DynamoDb for NoSQL. Both scale well and you need not worry about managing and load sharding/clustering your data stores once you launch them.
Middleware APIs - This is a crucial part. It is important to have a set of APIs (preferably REST, but you could pretty much use anything here) which expose your back-end functionality as a service. A service oriented architecture can be scaled very easily to cater multiple front-facing clients such as web, mobile, desktop, third-party widgets, etc. Middleware APIs should typically NOT be where your business logic is processed, most of it (or all of it) should be translated to database lookups/queries for higher performance. These services could be load balanced for high availability. Amazon's Elastic Load Balancers (ELB) are good for starters. If you want to get into some more customization like blocking traffic for certain set of IP addresses, performing Blue/Green deployments, then maybe you should consider HAProxy load balancers deployed to separate instances.
Front-end - This is where your presentation layer should reside. It should avoid any direct database queries except for the ones which are limited to the scope of the front-end e.g.: a simple Redis call to get the latest cache keys for front-end fragments. Here is where you could pretty much perform a lot of caching, right from the service calls to the front-end fragments. You could use AWS CloudFront for static assets delivery and AWS ElastiCache for your cache store. ElastiCache is nothing but a managed memcached cluster. You should even consider load balancing the front-end nodes behind an ELB.
All this can be bundled and deployed with AutoScaling using AWS Elastic Beanstalk. It currently supports ASP .NET, PHP, Python, Java and Ruby containers. AWS Elastic Beanstalk still has it's own limitations but is a very cool way to manage your infrastructure with the least hassle for monitoring, scaling and load balancing.
Tip: Identifying the read and write intensive areas of your application helps a lot. You could then go ahead and slice your infrastructure accordingly and perform required optimizations with a read or write focus at a time.
To sum it all, Amazon AWS has pretty much everything you could possibly use to craft your server topology. It's upon you to choose components.
Hope this helps!
The way I would do it would be, to have 1 server as the DB server with mysql running on it. All my data on memcached, which can span across multiple servers and my clients with a simple "if not on memcached, read from db, put it on memcached and return".
Memcached is very easy to scale, as compared to a DB. A db scaling takes a lot of administrative effort. Its a pain to get it right and working. So I choose memcached. Infact I have extra memcached servers up, just to manage downtime (if any of my memcached) servers.
My data is mostly read, and few writes. And when writes happen, I push the data to memcached too. All in all this works better for me, code, administrative, fallback, failover, loadbalancing way. All win. You just need to code a "little" bit better.
Clustering mysql is more tempting, as it seems more easy to code, deploy, maintain and keep up and performing. Remember mysql is harddisk based, and memcached is memory based, so by nature its much more faster (10 times atleast). And since it takes over all the read load from the db, your db config can be REALLY simple.
I really hope someone points to a contrary argument here, I would love to hear it.
We are building a system that would benefit greatly from a Distributed Caching mechanism, like Memcached. But i cant get my head around the configuration of Memcached daemons and clients finding each other on an Amazon Data Center. Do we manually setup the IP addresses of each memcache instance (they wont be dedicated, they will run on Web Servers or Worker Boxes) or is there a automagic way of getting them to talk to each other? I was looking at Microsoft Windows Server App Fabric Caching, but it seems to either need a file share or a domain to work correctly, and i have neither at the moment... given internal IP addresses are Transient on Amazon, i am wondering how you get around this...
I haven't setup a cluster of memcached servers before, but Membase is a solution that could take away all of the pain you are experiencing with memcached. Membase is basically memcached with a persistence layer underneath and comes with great cluster management software. Clustering servers together is as easy since all you need to do is tell the cluster what the ip address of the new node is. If you already have an application written for Memcached it will also work with Membase since Membase uses the Memcached protocol. It might be worth taking a look at.
I believe you could create an elastic ip in EC2 for each of the boxes that hold your memcached servers. These elastic ips can be dynamically mapped to any EC2 instance. Then your memcached clients just use the elastic ips as if they were static ip addresses.
http://alestic.com/2009/06/ec2-elastic-ip-internal
As you seemed to have discovered, Route53 is commonly used for these discovery purposes. For your specific use case, however, I would just use Amazon ElasticCache. Amazon has both memcached and redis compliant versions of ElasticCache and they manage the infrastructure for you including providing you with a DNS entry point. Also for managing things like asp.net session state, you might consider this article on the DynamoDB session state provider.
General rule of thumb: if you are developing a new app then try and leverage what the cloud provides vs. build it, it'll make your life way simpler.