Spring Tips: Redis

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
I spring fans welcome to another installment of spring tips today we're gonna talk about Redis Redis has become an adequate as sort of general purpose appliance that everybody is and installed or used at some point and it's made more readily available not least of which because it's simple to use simple to operationalize and simple to install but because it well first of all it goes out of its way to be accessible there's even support for example that someone might use it using the memcache D protocol and the company behind it Redis Labs has done a great job of making it as easy to consume as possible and a number of different target platforms so you can actually use Redis for example in cloud memory right they have they've provided the support for that using pivotal cloud foundry or pivotal web services are hosted multi-tenant cloud platform Redis labs also goes I think a step beyond they provide a number of features that make Redis really palatable for it so for example stock Redis out of the box the open source Redis has a strong correspondence there's one server one database now so I have multiple databases then it becomes a little TD so you have to run multiple servers they have a product that allows you to then manage all that right Dave Nielsen over at Redis labs he likes to joke that it is a hard DBMS right a Redis database management system in the same way that my sequel Oracle or post cards are our DBMS is but in their case of course they're talking about relational database management systems now Redis is most commonly known I think for for its use as a key value store but that I think dismisses or ignores the the large swath of features in functionality that that Redis provides there's a lot of use cases that are well supported by Redis that I think most of us just take for granted or don't even know they are there until we ignore so the goal here in this installment is to look at just this huge just just Swiss this amazing veritable Swiss Army knife of functionality that is Redis and to see how to build an app with it and see how different aspects of the spring ecosystem make using it and working with it very simple so we're gonna build a new application here starting at start to spring the veil and we're gonna take a manager of the auto configuration for spring spring boot and Redis building application here called gonna call this Redis so I don't see Redis like so and we use the data Redis support okay now you notice that there is actually a reactive variant we could have used that as well but I'm gonna use just regular Redis will use Lombok we're gonna use the session support we're gonna use the cache abstraction support we'll use the web support alright so we've got a number of different bits here that we want in our application in order to be able to to be able to build this application we're gonna build a web app so I'm going to use time leaf as well so just a lot of different functionality here that we can use you know to build a very simple application but we're gonna hit a lot of different points very quickly not focusing at any one particular thing this is meant to be a smorgasbord of Redis if you're welcome okay so I'm gonna build a application here ueo reddit zip open this up in my IDE and we're gonna then we're gonna then move in straight into the coast right so I'm gonna build an application in order to be able to deploy this into as we well later into cloud funder we need to add the commons pool dependency so I must remember to do that here waiting for all the bits to download all right palm that XML okay so Commons pool too okay and there we are there's our new server radius application and we're gonna build to some application so we'll start with what I think most of us are familiar with which is the Redis template now spring boot auto configures a couple of Redis converts here so let's look at the witness auto configuration here and we see that we are we have two configurations for two different Redis client-side libraries now the other thing you may appreciate is that Redis itself the spring data rate is supports look at the Redis template is very old this is one of the one of the first modules that we added to spring data after neo4j and since the very beginning I think this has been here for almost got to be eight years now right at 2011 2010 so a long time that we've had this support in spring data it's one of the original modules and so it's gone through a lot of evolutions but fundamentally at the core there's always been a few core concepts including this rightist template this rightist template very much like other templates in the Spring Framework eco system is a thing that handles tedious resource initialization and acquisition and acquisition and let's just focus on the business logic that we want to express so things like issuing queries and doing updates and and so on are easy to do they become one-liners usually and the things that we don't want to waste time on like you know setting up a connection and setting up a session and all that stuff and managing all the result sets and all that stuff just be able to iterate over them all that stuff is managed for us by this template this template is keyed it's genericized in terms of the key type that we're going to use so remember Redis is fundamentally a key value store but the values themselves can be all sorts of different things you can have other dictionaries or Maps right or they call it a hash as values you can have a cue right so you can simulate pub/sub with redness you can do you can have geo spatial indexes as values you can do atomic numbers and semaphores these kinds of things as values so there's a lot of really sophisticated values that you can put there but ultimately they have a key and of course your values could just be arbitrary you know blobs of data and and that is the first thing that we have to understand here is that Redis doesn't care how we encode our data that data can live in Redis as just a series of bytes for example it can live as JSON you know you know whatever you want it's up to you as a client you of that database to specify that when you create the template now here as a quick point I want to point out there's two different configurations for classes for two different types of clients so jealous and lettuce are both two third party Java clients that can be used to talk to to Redis and we support both of them we provide connection factories for both of them so here we're gonna create a rate of template which in turn injects the Redis connection factory one of those you know it's gonna be one of these implementations you know automatically I think there's actually a third one but it's just no Auto configuration for that third one so we we support that we can configure how we see relies the data all right so we've got this custom raddest template let's go ahead and create our own for now just to see how it works and by the way you can see down here we've got a string Redis template this string Redis template is just a Redis template with keys and values of type string right and you can see here that they have already specified Eliezer's alright so this is a string sterilizer for everything right by default however when using Redis with a with it with the JVM based application you get Java IO serialization so the default configuration is Java JDK serialization which may or may not be which one if using Redis entirely in the context of a homogeneous sort of Java based or JVM based application then it's just fine but if you're using Redis with multiple clients and multiple languages and of course you want to you want to move away from that and you can so let's let's take a look at let's take a look at custom configuration here okay and we'll create a new Redis template and our with template is going to have custom configuration for serialization so let's say that we have let's just for now as an example we're not gonna we're not gonna keep this here but let's just create a class of type cat and it'll be string cat all right tell me I want to have a rest template that lets me work with keys and in cat name and cats right and so the who cares about this type of but suffice it to say I want this to be premised to that so now I'm gonna have a read of template of type string and cat alright and I need to now configure value sterilizers key sterilizers hash key services and hash bag of satellizer so in practice that's actually only just two in this case so it's a it's a Redis sterilizer of type whatever are new and the disk in this case I want to just use a generic Jackson to JSON sterilizer serializing to or I can even say Jackson there we go cat cat class so this is the value right we're going to say value and this can be cat if we like it doesn't really matter and then we want to do one for keys so keys I think will just be fine with a string a string Cyril is ourselves Redis string see what we got we have a number of different options here we want the string right a steriliser that's the type so string Redis serializer and we don't need to see parenthesize and I know genera size it there's no parameter there so the values we're going to be encoded with this and the keys with that so key cyril laser keys template dot value sterilizer values template dot hash value laser values template dot hash key sterilizer keys all right so we've been now you know hash values and hash keys and just regular keys values and we're gonna use the same as your lies so this is actually this is fine we could leave this as is but in our case we're gonna express a number of different term configurations beyond just cats and I just want to demonstrate how this would work and of course I don't need that don't even need to be public so that would effectively replace the configuration that we have in the Auto config if we wanted it to but for our purposes it's the prices to leave the Auto config as is I just want you to appreciate some of the flexibility that you have here in configuring you know Redis and its connectivity now this some Auto configuration lets us work with a with a a template right we can use the template so let's do that we can create a beam of type of application writer but we're gonna create so many application runners and I wanna be able to you know sort of I want to have a way of just sort of setting off each application winner so we can see the examples in the output as we developed today so I want to create a little thing here that takes an application runner and then adapts it and it prints out the title before it runs our runner so passing on that and we're gonna inject the lawn care reusing a Lombok to do that right so I'll see a blog and I'll say log that info and then title will be to uppercase and there we are alright so there's our titled runner and we're gonna do we're gonna use this a fair number of times so let's go ahead and build our first application our first application using this template well we'll touch on a you know a fairly under-appreciated feature which is that Redis can support geolocation all right so we're gonna say I want to do geography here okay we're gonna create some geography we're gonna create a title runner geography and I'll create a lambda here args all right now this title runner it's going to write data to the database using the this template that the straightest template that we've got here so renas template of type string and string it's fine for us we use the string writers template there are t dot and we're gonna get the opps for geo so that's going to give us the geo operations not the hash operation it's not the ones that we can use to manage distributed lists or values or you know anything cost or primitives but instead the geo operations I'm gonna dereference that stored in a variable here okay and we'll use the geo or use geo here to to record a few records into the database so I'm going to say add and when I add a record around a city and Italy this is actually borrowing from the domain inside of the spring data in the side of the spring data examples projects so if you go to github.com for spring - projects for spring - data - examples you'll find a number of different options here okay so we're going to use that the point type or extreme form of data Adagio and this is actually a type that's in the spring data framework and here I'm gonna tediously copy and paste or rather I'm just gonna type out loud so three six one three eight nine okay three 8.11 five five five six alright and that's gonna be our okay that adds one point two to the geolocation so it's a it's an index around that key or near that key associate with that key for a city so here the parameters if you want if you look at this it says we're gonna add the key the point and then the name of the member right I'm going to do this three more times the second time will point to one 508 seven two six nine three 7.5 oh two six six nine and this place will be called cat timing you and here is the second example the third example rather one 3.58 and that's for threes I think right so that'll be fine and then it's a three seven three a 7.3 one six six six seven okay seven so I think that's right let's go let me just reconfirm here just very revisit these numbers one three three six one three eight nine one three three six one three eight nine okay good three eight one one and then five five five six so three eight one one five five five and that six good second set is one 508 seven two six nine one 508 72-69 good three seven five oh two six six nine three seven five oh two six six nine great next set is one three five eight three three three three so that looks correct 37.3 one six six seven three 7.31 667 good so we've got now the correct data now we're going to use that to to create a circle I'm gonna draw a circle around one of these points and see what falls within that circle so I'm gonna say new circle new point okay and we'll use one three five eight three three three three seven three one six six seven so one five five eight three three three three seven three one six six six seven good and we're gonna tell it to specify a distance of that you know around that point using 100 kilometers so Redis geo commands dot one the other one dot distance unit kilometer is very good so these are our circle and now we're going to use Redis to ask it what points fall within that circle so we can say geo results are actually can just say this data or RT no sorry geo dot circle radius and we're gonna ask it for all the things in that radius we're gonna say within that key and then we'll give it a circle point here and that'll give us a collection of to your results all right so now we can visit each one of these geo results here and let's see it's gonna be geolocation and yeah results were gonna visit we're gonna visit each result dot for each G our log info jr. to string all right so um we can get the content I suppose actually it might be even easier this to that geo results thought get content dot for each okay so see logs info see it up to string let's see what that gives us let's run this program and see all right so two of those points fall within that region Palermo and oriental are gentle gentle sometime I get all right very good so that's you know a simple example but it works and you know obviously you wouldn't hopefully had this hard have this hard-coded this would be something you could load in from a GIS database or something like that but a lot of possibilities here right you can do something very very very quick work with geography here to support you know common geospatial kind of queries that you may may want to support an application now that's one common use case that's a very common use cases is to to use geography to to work as geospatial data and it's just one of those it's just one of those many things that Redis does it just does it well and you while you could use post GIS or in the post cos world or MongoDB or Couchbase they both have geospatial crit support as well if you've already got Redis you might as well just use it right so that's a one of those many things that you can just do it out of the box nicely now let's talk about one of those other things that that template supports right we saw the reddest template supports are T dot hashes right so hash hash Ops for hash and hash gives you a hash operations and what this lets you do is create a map that's associated with a key which is great so you have the ability to store basically records you can store a whole whole record associated with a key you could say here's the whole you know the first name and last name and they email on the ID for this username or whatever or you can just look it up by the ID so that's a natural thing to use to store records and in fact we can support repositories so another concept another tenant of the spring data projects is this concept of a repository now a repository inspring data is just a convention of configuration of centric approach to building queries based on the names of methods in interfaces and spring data has a number of different implementations that work with different projects and these are these are meant to support as much as we can but no more we're not trying to provide the illusion that certain things are possible for things that don't support it but we can actually make basic crud style repositories work with Redis so let's do that let's create a a simple type here called a order and it's going to be serializable and we want the order to support an ID so we'll say private long ID using the spring framework data let's bring down a ID type there it's gonna have an indexed date right indexed private date when all right tell you till date and we'll have a reference to a list of line items all right so find items line items very good now this type of course we need this type class line item implements serializable and we'll come back to what that type does but for now we know that this type are our type is going to support it's gonna be persisted in the database using Redis hash functionality here we know that we need getters and setters so I'm gonna say at data and all arcs constructor and no rocks constructor you don't actually need the Newark's constructor for spring data it's not like jpoa you need it but but I want a no argument constructor right because it's just convenient these are all may be optional but that's it good program practice says if you want to have a valid a valid Li construct object you should learn how to be able to construct that through the constructor so maybe I don't need to know our constructor let's just leave it for now okay now I have a older not not quite what I wanted so order there and the order will have line items and the line items will have at indexed a private long order ID all right and will have an ID here at id private long ID and that's it private string description now we want the line items to be persisted as well nine items and it's gonna have all the same things as before now we need to create repositories to produce this now when we say indexed index means that you know it's gonna create a key it's gonna be able to I'm gonna be able to look up this record by this value as I keep sort of right so it's going to create a customized if you create an extra slot that I can then use to quickly reference this type by this value and I wouldn't have to worry about that too much but this is critical when using Redis these types your Redis hash and had indexed are specific to the spring data Redis support the ID annotation is generic to the spring data Orem abstraction the mechanism that underpins this but you know we went out of her way to make this work for Redis and it's it's very valuable right it gives us the ability to model complex things and still do so in an efficient way but that said we don't promise that you know we can do certain things that are just not reasonable for something like retinas which doesn't support perhaps sort of the ad hoc query support that you might expect for using a my sequel or something like that right so line-item got to manage line items whose primary keys of type long and interface order repository it's going to extend crud repository whose payload of type is order and ID is long alright so there are two types now maybe I want to have a custom finder method here let's say I want to do collection you know let's say I want to find a an order by its date fine by when right so date D and I can do that that works actually just fine with with our Redis abstraction here so let's say we want to create some data we have to create an application runner that supports this data so red is so repositories and what's a return titled runner repositories args and we'll go ahead and run that and the repository we're gonna write some data to the database we're gonna have a couple of Records we're going to see well first so I need to create an order ID so long order ID and I need to generate a ID all right it's all quite a convenience method here because I'm going to do this a lot today so we'll say long temp equals new random dot next long and that may be negative so I'm going to say math dot max temp or temp times negative one and I'll return that so there's our generated ID and what I want to do is I want to create a few different line items and I'll save those first so arrays dot as list new line item order ID generate ID and we're going to call this a plunger for example and a new line item will be order ID generate ID a soup and a new line item will be order ID generate ID and you know what's a good one a coffee mug sure all right so now we've got these types got these records I'm going to save to the day base so so we need to actually visit each one and then save them so I'm gonna say item list dot stream dot map and a pass in the line item repository so let's do that here so line item repository and here I'll say repository dot save it and it is of course the generic there replace it with a method of reference if we want and then we need to subscribe so we need to actually visit each record that comes back and we'll say for each L I system out I guess we can just use log right no problem li so I lined up to string very good look at that we've got now these different records and that should work let's go ahead and run this to see what we get okay so it's those the three records after they've been saved now let's create the order order equals new order here the order ID will pass that indirectly the new date will be this one right here and Elena the item list will be this and now we're going to save this as well we're gonna say to inject the order repository so order repository and I guess I can rename this to line item repository and I'll say order repository dot save order and that will give us a result that's been saved in the database and we can then inspect it we can say order repository dot find by when where order dot get win so this should return if everything goes to plan retreat you know found and you know it's gonna return a collection I suppose or we couldn't even do an optional if we want to we could have said optional of T find by whatever if we know there's only one or zero so there we go so we've got that now and let's just visit those records so we'll say found out for each o log dot info found out to string alright so I'm visiting the data that's coming back from the database after I'm querying it after I've written it to the database so I'm gonna run the there we go so he wrote it to the database we found it got this record back and of course we got the reference to line items therein right so the description is the plunger the soup and the coffee mug all that it's just been done for us automatically now if we look at what's happening behind the scenes here and now if you can see it's actually created a whole schema that's managing all of this for me right it's just managing it for me I don't have to worry about it and it it's got indexes it's got the a relationships it's got all these keys orders when etc as all as being done for us so we don't have to worry about you know any of this kind of complicated stuff riddance is perfectly happy to do it it's just that there's a little bit of manual assembly required here and the spring data abstraction does that work for us so that we can now get the best use out of Redis here okay all right so that's a very simple example that's just a we're taking we're using hashes behind the scenes right this is actually fundamentally turning into things like hashes and and and keys and values it's using the fundamental atoms of Redis but it's doing something very sophisticated on top which allows us to focus on a higher-order business logic concerns so the next thing that we want to focus on when we look at and our little tour here of Venice is a using it for publish/subscribe right this is a common use case I want to pub I want to communicate from one note to another using some sort of middleware where I could of course install Apache Kafka or RabbitMQ and these are growth these are both fine choices maybe even a JMS broker although there are reasons why you might want to avoid that last one but Redis is actually you know it's fine it's it's not it's not it's not the most feature full message broker in the business but if you've already got it installed and you're trying to do simple pub/sub then this might be all you need especially if you're just doing a status update or it's it's fine that you might lose a message here in there right if you're trying to do finance transactions then yeah okay probably a probably better to use something like rabbitmq or Kafka right but here we're just going okay we're gonna you know let's suppose we have a chat right and we're one of our status notifications or you know presidents awareness or something like that this is a perfectly fine choice because it's gonna be in memory it's gonna be lightning-fast and the clients are gonna be able to you know publish messages to a topic which is actually just a key and with us a queue behind the scenes and and then they can consume it so we actually have it support for this in spring as well so let's create am a an application that sends a message so here I'm going to create an application writer being an application runner pub/sub and we're gonna return a titled so publish sub scribe okay and scribe there we go args and we'll use this publish/subscribe endpoint use this runner to now send a message and that's that's the easy part I mean both both producer and consumer are easy really but I'm gonna use the rest template here so write it in a rightist template of type string and string RT and we're gonna say R T dot convert and send and we're gonna create a channel here a shared channel a topic so private final string topic I guess whatever who cares chat okay and I'm gonna say that I'm gonna send a message to this topic so top pick and we can just you know there okay and the message I'm going to send is any arbitrary message in here it could be you know it could be um json encoded it could be a string it could be whatever you want so but we're relying on the default string sterilization here so i'm just gonna send a string hello world at instant dot now dot to string alright so I'm sending a timing coded message and now I need to consume that message now I could spit up another note and it would be very easy but since we already understand how that would work and I want to save myself some typing time I'm gonna go ahead and create a message listener consumer here in the and the same the same note so I'm doing I'm sending a message into Redis and it's gonna be delivered right back to the same node which is acting as a client so it's actually it's making the same network hops as it would word it you know weren't to actually be to give to given projects but I just want to demonstrate how this works okay so that's now create a message listener that's going to respond to messages and then in spring we've had we have this concept of a message listener container right so a message listener container I'm gonna use the rest that Redis message listener container and this reddit reddit message listener container needs a witness it needs a message listener so let's create the Redis message there's our container like so and the MLC needs a connection factory of course oh well inject the Redis connection factory alright and I will say CF and we'll say m LLC dot we need we didn't need a message listener alright so we need to do that as well and the the message listener will be ml we'll come back to that in a second and then we need a pattern topic so I'm gonna tell it to use this dot topic right same as before and that's it that's the MLC itself but we need the message listener so let's do that that's the easy bit and so ml equals new message that's not a very simple interface and here we're going to take the data from the pain wood and just log it out right just just confirm that it's as we expected it to be and and enumerate the value all right so let's let's do that here we're gonna say string string equals a new string message dot get body those are bytes that come in and we want to log it out so long that info new message or message from ok and it'll be this dot topic or the topic okay STR very cool now we can use that messagelistener all right good replace it with a lambda so they recall there we go so there's our mrs. position container and our incoming messages and we can now read the data let's let's let's see what happens so let's go ahead and run this now keep in mind this message is going to be received asynchronously out-of-band so we're gonna see the header for publish/subscribe be printed and it might actually let's say publish/subscribe gets printed where's the result found did I do something wrong message listener container messagelistener message they turn the container returned that I don't see it doing uh I see it doing this don't I so there's they published there is a publish/subscribe in point and then I do it the wrong way around convert and send to the topic hello world yeah that looks right doesn't it so how is it I'm missing something obvious clearly publish/subscribe and the topic let's say it's called chat log that info can we try this again this time with the debugger let's see what we get it's not quite working the way I expected it to so let me see it's a message this in a container Renaissance Center yeah there is the name of the bean I was some other beam is conflicting without bean type so I renamed it to listener and I got message from chat hello world blah blah blah okay so that actually worked that was a I was a mysterious one so they were going I guess we just learned something new don't use the name and that I had just had before to name your container but once you do this once you've changed it from that it'll work so here we go we have a message there's no container that's responding or that receives the incoming message and it can do something with it so now you can do all sorts of interesting things here you could create topics based on you know okay so this thing here is a topic of some sort you could create a topic that has a unique key that only one producer and consumer would agree on you can do broadcast them you can do all sorts of things you know here with this basic messaging primitive right so this is yet another thing that's a kind of just supported out of the box it's a little-known feature of Redis that I hope you'll take advantage of right we also support using Redis for keys and values naturally and there's a lot of different places where you would want to do that including in caching right so when you cache data let me move this code to the top of the code page there there we are and what we want to do is want to cache data that we've you know that we've created that perhaps expensive to arrive at so let's say that enable caching at the right top here and so an able caching and in our build you will see that we have here in the build we have the spring data Redis dependency and that dependency has a a cache manager abstraction so it's gonna work in conjunction with the at enable caching annotation and if we're it to do its work it's going to need a cache manager implementation and we can configure that fairly easily so let's do that here we'll say that bean I guess we can do it here here at bean cache manager Redis cache you know okay and that's will create the cache manager and we're gonna say return new we're gonna use the rest cache manager builder method here so - cache manager dot that builder I'm gonna inject the witness connection factory will say builder dot CF that build alright so there's our Redis cache manager abstraction implementation and now we can create something stateful that has that's protect potentially performant and expensive and we want to be able to memorize or remember the results of a method invocation so I'm not gonna do no the goal here is not to do a whole introduction to the cache manager abstraction although you should absolutely look into it but instead I want to create you know I want to demonstrate how this works seamlessly with Redis so I'm gonna create a order service let's just say okay so an order service and this order service is going to be cashable so I'm gonna support caching results that come back from this method so public order by ID looking up the ID here I'm going to say add cacheable and we're gonna say well you know order by ID so it'll look up the records from this method it'll take up there it'll look up and look up the lookup and Redis any of the data that comes from this let me try that again when you call this method it's gonna see first of all if there's a results already stored in the in the record in the database with this key and another key that's you know a combination of key based on this name here and the arguments to the method of location and there are arguments that either sanitation's that you can use to to control you know which which keys should be used and which which which invocations should be used to evict data from that from the from the cache but let's just assume that we want every argument there to contribute to the key that is then used to return this resolved result so now let's say return new order passing in the ID and a new day tune or just passing empty a list of line items there now what we're gonna do is we're going to create a artificial sleep so it'll take a second to solve a second if somebody wants to call this without having having it already in the cache and then otherwise let's just make it ten seconds and it's actually perceptible okay so and then otherwise uh it'll just go straight to thinking straight to our Arbutus cash okay so let's say at log and we'll say well that error info I guess exception actually doesn't even matter was just to do throw new running time exception all right it's all right even care about this don't even need the logs so we're creating an artifact we're just returning the result to cares about the result but we want to want to induce that artificial sleep to make sure that we can see how fast it's going so now let's call that order service from a repository from a runner and prove that it's working so it's got a new beam of that specific application runner so cache and we'll use this order service which has been created for us order what did I save it as order service order service I am NOT going great with that word today so order service and titled caching a good so there's this and in the in the order service we're gonna call the method so we're gonna do so a number of different times so what I'm going to do is I'm going to measure each invocation so we'll say runnable are how we're gonna do this what's the easiest way to do this we can create a method to save the let's see class yeah private long measure and we're gonna take a runnable are and we will save the current time so start equal system current time Milly long stop equals system that current time mini and we're going to run our dat run and what is that about private okay and we're going to turn return stop - start so that's the measure method there and we're gonna measure some runner bulls and the runnable is gonna be measure it's gonna be this so I'm going to say run order service dot by ID 1l all right and so now I'm going to print out the timings for that so let's say we have log that info first and we'll print out measure okay so two times two and three times so we'll have now a three invocations of the same basic thing it's gonna run this invocation each time and and we'll see the results hopefully all right so we'll say you know call this and then show us what we got so now let's see why is this still upset oh this because the M inspection disable that inspection okay now let's go ahead and run this again this time we're gonna run it's gonna be called caching while caching the same lookup it the first time it should take whatever we said ten seconds so it's calling caching taking its tedious amount of time here of course there is also the first time it took ten thousand and nine milliseconds ten seconds and nine mils late so the actual access on the first time is nine milliseconds the second time it took two milliseconds in the third time took one millisecond or you know less then so this is this could actually be nanosecond granularity at this point I don't know I'm just got it it's giving us the it's rounding up of course right so the point is we have the ability to go really quickly for using memoization right and we get that for free and behind the scenes you know if we look at this keys we have invocation it's based on IDs in there so let's see I'm not even sure if I can spot the EM it's about the invocation the incantation that's being used to make that call alright so orders oh and if it's that one anyway that's being done for us automatic oh they're just ordered by the one right so that's the incantation and if we look at that wait if you look at that value orders okay so keys and get value that's read okay so we're trying to get the value for a key and if I'm honest I don't know the command that you're supposed to use them in the rid of CLI I just always do it from from Springs so is it get key let's try and get something okay there we go that make sense so paste there you go so there's the Java cos encoding of that object again you can use a custom sterilizer but you can see it's it's got the same information that we need there's the order and aligned items and you know all the bits that are required to to make this work the Java util date all that stuff is there all right okay so there's the memoized version of the the record and that would work you know serialization issues notwithstanding that would work across multiple virtual machines as well so if if we have ten different applications web application and they're out there making calls to this order service and one client makes a call on one web service one one application instance then other clients accessing the same record another application instances would benefit from that lookup and of course you could have cache evict annotations to evict you can say public void update long ID and you can say you know cached evict this record based on this this method call so we would actually invalidate the record in the repository based on the the call all right so now speaking of web another very logical sort of use case for for a cash like renas is to use it for a session storage right so let's bring that application backups readiness application we've got this application now running and the application is running and we've got um you know no WebM point right now so let's go ahead and do that we're gonna build a simple web endpoint that's gonna use the HTTP session so we'll say what do I want to write I can do it in here let's say class session you know cart session controller alright and this is going to be a logged and spring MVC controller that's going to have a session attribute called cart and we'll come back to that in a second and the data we're gonna create a model attribute so what's gonna happen is we're gonna we're gonna return a shopping cart okay so class like so and the shopping cart will have a collection of orders orders and this has to be all C reliable so you should probably use a little bit more care here but I'm gonna be using a very simple and a very simple sort of thread naive approach here so I'm going to say public void and order and I use an order object here so order order and this orders dot to add order good and I'm gonna have another endpoint here that returns a collection of order get orders all right let's return this dot orders dot there we go so that's my very simple shopping cart and we want the shopping cart to be persistent so I'm gonna make it serializable as well okay and we want to support where's my for matter on that expands part of the problem so now let me confirm that's working good all right so there's that this is session attributes good so what's going to happen is when this spring MVC controller gets loaded there's gonna be certain endpoints here that are gonna look for a cart and then look for the cart in the session if they don't find it they're gonna have to create a brand new object that they can use as a backing beam for data that's gonna be created in the lifecycle of one is handler methods so it's gonna look to a model attribute method on the controller to vend a new instance of that of that cart so a return new shopping cart so this is gonna be empty I'm gonna log you know producing or creating new cart alright I'm going to log that and then I'm gonna use them I say that's create an in point here called orders that you know dot Redis or whatever just call it with orders if you want that's gonna return an HTML page rendered with time and if and that's gonna inject this model attributes a model attribute cart and it'll be shopping cart so a shopping cart to cart and we're gonna create a model lets bring me some model to render the the view here and the model is just gonna have some data in it mono add attribute orders and it'll be cart died get order so this what we're gonna do is whenever somebody goes to this endpoint we're gonna add a new order and we're gonna have a private atomic private atomic long right so private final atomic long new atomic long and I call this IDs and we'll add the order here like so we'll say ID dot increment and get new date and collections dot empty list so when I add a new record each time and then render a view called orders that hasn't activated them in the view called orders that we're going to iterate in the view so to review somebody's gonna call this endpoint we're going to add a new record to the cart in the session if the cart if the session doesn't if the record doesn't exist in the session then it's gonna call this model attribute method and then it's gonna it's gonna use that - it's gonna be injected here as a parameter and I'm gonna add a new record so over time given the same session we should see an increasing number of orders in the cart but if you start a new session it's just it should be set back to zero and we should see it saying creating a new cart right so first time it'll it'll call that okay now we need a template some sort of view so this is why I added time they fear so source main resources templates I'm gonna create a file here called orders dot HTML and the orders that HTML file we're just gonna we're just gonna you know I won't I'll spare you I'll spare you all this live coding there so desktop Redis source resources templates or to study HTML clipboard good man so there's that so very very simple Redis orders right right as orders and what we do is want to render a div element but rather we're gonna render two spans for every order Oh in the orders I attribute from the view Evan model rather so when a dereference the ID and the when attribute right in the order so I think that should be in it the only thing we need to do now is to enable spring sessions spring session is the facility that lets us swap out the HTTP servlet session and replace it with with a pluggable session store of our choice and here we're using Venice we could use the H cache or in memory or we can use MongoDB or JBC or hazel caste or you know a number of different options here but what Redis is a fine choice for this so we're gonna add rid of set of sessions and we start the application so now if we go to where did we say we're gonna go to for such orders in the browser localhost 8080 for special orders there we go 1 2 3 4 5 6 7 etc now if I create a new instance go to the same endpoint you can see it's got this you know it's just ID is number 9 so it's obviously a different instance but it's increasing you know independent each other so right so I've I've got two different sessions here and that state is being stored in Redis so keys and you can see it says spring sessions expires and there's another attribute in here somewhere if I can there too spring session expirations spring session etc so we've got different sessions being persisted here and managed for us by our different application instances so if I were to spin up another instance of this application in this and then and then somehow call that an application on port 8081 for example then given the same cookie the same clan said cookie I should get the same result right so there's no that's the you know that's a very simple example of using Redis as a session it's just pluggable where we could actually inject the I'm using spring MVC here but you could inject in your spring MVC controller you could say HTTP session session and then do that as well it'll work right it'll be in a plug-in to the spring session adapter that we've we've automatically configured for you so that that works you know independent of the programming model here any you can actually create a web service I had web server annotated component you know a straight-up servlet and then that would in turn also don't get to read us here so that works at every tier and it just happens for free so now we've got a horizontally scalable session persistence which means that if a node falls down and they get full they get load bounds to another node the session state hasn't been lost right okay so now now that we've got a web application we've got a number of different use cases demonstrated here I think we should we should deploy this all right so I'm going to take this application I'm gonna add a Cloud Foundry manifest to the application so CD Redis copy desktop Redis manifest here and you can see that if I look at the manifest the manifest says that the application is gonna be called spring tips Redis and it's gonna use a banking service of type spring tip furnace and again I'm using pivotal web services here and I can go to CF marketplace and I'm being given all the different services or service offerings for this hosted multi-tenant cloud offering kind of like Heroku or something like that and we have here a Redis instance where is our Redis support new relic no PMS equal PQ - cloud Ebola so there's are you know different different quotas different SLA options here and I've got a instance of this CF which is sort of for service I've got an instance of this st vitus Rinna's cloud 100 megabyte plan and I've got an application called st witness i'm gonna now cfd - f st Redis okay so I'm deleting the application that's already been deployed so it's now being unbound from the Redis instance and I'm gonna delete the service I'm gonna delete CFDA - des - f st Redis so I'm deleting the service as well so now we'll have a brand new everything I'm gonna create the service on new so CF c s st Redis so we read as cloud 100 megabyte st Redis okay so there we go and now I'm gonna do a maven clean package and that's going to build the jar the application the Springwood application it's gonna run the application so we'll see all the same familiar logging that we saw when we ran the application in the IDE and they're gonna deploy it to the platform alright so now we say CF push - P target Venice and we're gonna give it a logical name called st vitus but we could you know I think it'll automatically but I think it'll merge this push command with the manifest but let's just yeah I think I'd be fine let's just try it creating app st vitus using round binding this route to that uploading this I'm I'm not sure if we've already bound the st vitus to it or if it's going to consult the manifest oh yes it is look at that using manifest so it is already bound the service of the names st vitus to the application so now it's uploading the application it's gonna the platform is gonna look at the incoming artifact it's gonna realize that it's a jar application it's gonna give it give it a file system that has everything needed to read to run the application in this case a job a virtual machine that'll give it a route which we saw here is st vitus dot c of apps that i hope and let's see what we have here so it's gonna use a build pack that's the thing that decides what file system is required to run the application it's gonna choose inevitably the the Java build pack and then it'll start the application up it'll turn that filesystem into a container that it'll then schedule across the cluster now what we can do is we can actually cluster our application we can say CF scale - I - and effectively double the number of instances of the application itself but they're both talking to the same persistent right a store so even if we hit different instance of the application we'll still get our data okay so let's see waiting for the root the build packs to kick in good creating the container uploading the application now the UM the artifact should hopefully spin up here any moment now upload complete I'll put in complete not sure exactly what that is zero of one instance is running one starting there we go so there's our application up and running at this endpoint let's try it out okay and it's called orders right so first call second call third call and do the same thing here alright so now we've got an application you know two different two different sessions being persisted now let's actually go ahead and scale this up okay so CF scale - I - st - right so I'm going to double the load on that application instance CF logs I'm gonna follow the logs now for this instance so as I make requests over here you can see they request coming into the application on the left so router 11 router of 0 let's see where does it actually indicate yeah also the other application is still coming up app proc web 1 good so we got now two different apps being configured a way for them to spin up and we'll start to be able to round-robin the requests across multiple instances all right so okay refresh refresh refresh notice how in this case since we're running its we have the same session but it was handled on a different JVM and we know that it's been handled on a JVM because the ID is 3 all right so remember we have that private atomic long well this is JVM specific you know its intrinsic state but the internal state the external state which is the session itself that's being managed by Redis all that's just transparent so you know and we have the same host and we have the same it should be cookie same session cookie it's hitting the same host you know we have a load bouncer behind the scenes and we're getting different sessions right we're getting different application instances we know that because the application of state is different across those different ATMs and but we are still able to see and work with the same shopping cart on both notes so this is one of the examples of Redis just being a transparent you know thing that you can just layer down into layer into your application and get all this amazing functionality now we've long we've looked at a few different things here we looked at caching related meditation sheepy sessions we looked at repositories we looked at geography geospatial support I would have to publish/subscribe support we looked at you know you know caching just generic caching itself we looked at a number of different things here but we've only begun to scratch the surface Redis is as I say a variable Swiss Army knife of functionality it supports on a number of different things and in the spring ecosystem we use it to great effect and every layer that we can so we even have a project called spring pod gateway it is built on top of the reactive support in you know in Spring Framework five spring web flux and all that and I've done previous videos on spring card gateway itself and there we looked at using spring cloud game we need to create a rate limiter well it has to keep external state extrinsic state somewhere so it creates tours that in Redis for example and that's actually using their reactive Redis spring data module which I haven't even bothered to use here because it's it's still just you know all these ideas apply it's just very convenient to know that you can use this in a traditional servlet based architecture as well so with that my friends thank you so much for watching I hope you enjoyed we'll see next time you
Info
Channel: SpringDeveloper
Views: 16,618
Rating: 4.8571429 out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud
Id: _M8xoagybzU
Channel Id: undefined
Length: 67min 41sec (4061 seconds)
Published: Tue Apr 17 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.