# Implementing GET, SET, and TTL Commands in Redis | Redis Internals

## Метаданные

- **Канал:** Arpit Bhayani
- **YouTube:** https://www.youtube.com/watch?v=1rnEpo56LFk
- **Дата:** 26.04.2026
- **Длительность:** 22:08
- **Просмотры:** 3,342
- **Источник:** https://ekstraktznaniy.ru/video/49982

## Описание

System Design for SDE-2 and above: https://arpitbhayani.me/masterclass
System Design for Beginners: https://arpitbhayani.me/sys-design

Build Your Own Redis / DNS / BitTorrent / SQLite - with CodeCrafters.
Sign up and get 40% off - https://app.codecrafters.io/join?via=arpitbbhayani

# Recommended videos and playlists

If you liked this video, you will find the following videos and playlists helpful

Redis Internals: https://www.youtube.com/watch?v=h30k7YixrMo&list=PLsdq-3Z1EPT0eElcdOON9fdaeaQjlyXDt
Redis Internals Reading Material: https://docs.google.com/document/d/1lHKI6bia3ZEPoAKgXWIm_SKv_Sii1qtN3EYMEdxKpEQ/edit?tab=t.0

System Design: https://www.youtube.com/watch?v=o7qLKfILuD8&list=PLsdq-3Z1EPT27BuTnJ_trF7BsaTpYLqst
Designing Microservices: https://www.youtube.com/watch?v=JPj6mhVLQN0&list=PLsdq-3Z1EPT0ug8eizS71G6LZb6-4FAFt
Database Engineering: https://www.youtube.com/watch?v=-htbah3eCYg&list=PLsdq-3Z1EPT2C-Da7Jscr7NptGcIZgQ2l&pp=gAQBiAQB
Concurrency In-depth: https://www.youtube.

## Транскрипт

### Segment 1 (00:00 - 05:00) []

so in the previous video we made our radius implementation concurrent which means that now we are able to connect multiple clients concurrently to our own server right so now in this one what we would be doing is we would be implementing three of the most critical commands get set and TTL so before we jump into our implementation let's first see how a normal ready server reacts to get set and understand what kind of edge cases that we would need to handle so on the top right I have my like always I have my redis server running on Port 6379 and on the client what I would do is I would be connecting ready CLI on Port 6379 and now when I run it now what I can do is I can set a particular key I can pass a key K with value B and it will be setting the key K with value V and if I do get on key K I'll get a value B right apart from just setting a key and a value now if you but before you jump that if you clearly see if I do a get key or get t k what I'm getting is I'm getting a string V which means it's a bulk string right now in the set you would also see a bunch of parameters that I can take the parameter that we are interested in is ex is basically setting an expiry to it so you can specify the day I would want to I would do like I'm basically setting this key with value V and now what I want to do is I want to also set an expiry to that let's say if I set 5 which means after 5 Seconds the key should be deleted so if I do a set K comma V expiry of 5 if I do get k it would give me the value B but if I do it repetitively as soon as 5 Seconds have elapsed you see it returned a nil right so as soon as key is expired if I pass in or if I do a get on an expired key it gives me okay it basically gives me nil right okay so in set what if I don't pass an integer value what if I pass some random string it says that value is not an integer or is out of range so basic syntax check and then if I let's say don't pass anything it gives me syntax error so these are basic checks that we would have to apply when we are implementing set right okay now when we do get what do we do what do we get key K but k is expired so now we didn't get anything so when I am getting a key that does not exist it returns middle right okay but if I'm doing a set key K with value V and if I do a get I'm getting uh if I do a get on key K I'll get the value B right but what if I'd want to see what the expiration time is like for example if I set up value if say I set a key K with value V and expiration of 10 seconds and I want to see the expiration the time to leave remaining of that key there is a command called TTL it returns an integer that decrements like that shows the amount of time after which it would be elapsed and you saw it returned five three two one and then it returned minus 2. so what TTL command does is TTL command responds with the amount of seconds or the number of seconds left for your key to get expired right that is its job so if I'm doing a TTL on a key that does not exist it returns me -2 but what if I do a TTL on a key K1 whose x expiration is not set if I do a TTL on key K1 so key exist but there is no detail set on it returns a minus one so we see three typical written values of TTL the first one is -2 which means if I do a detail on a key that does not exist we should return minus 2 if I do a TTL on a key whose expiration is not set it sets it returns minus 1 and otherwise it Returns the time that is elapsed or sorry remaining for the key to get expired to get Auto expired so now let's Implement get set and TTL in our own implementation okay so now what we would do is we would go through and now we would do an exhaustive Code walkthrough on how it is actually implemented so first of all what we would need to do is we would need to go to the eval. go file in which we write the implementation of all the command and add support for set get and TTL similar to how we did it with ping now we do it with set get and TTL all of them takes arguments as an input and a writer which could be a socket connection or a file descriptor and we would be writing the code for that so first let's start with a simple set implementation so now set what would set do set as a command would get in arguments key value and any other extra arguments that we pass in and if you remember in the second third video you I talk about that when you're ready CLI sends a command to

### Segment 2 (05:00 - 10:00) [5:00]

your ready server it is always sent as a string as a as an array of strings right so this is what we are getting in the argument so here what we would know is in case my number of arguments are not are less than equal to 2 which means it's definitely it is like it is definitely not having the key or the value we would want to send an error so that's the first check that we are making that if the number of arguments are less than equal to 1 so then it's definitely that we are giving like we are not passing the required arguments and then we Define variable key value and expiration that the only thing that we are implementing is basic expiration in seconds okay now what we know that argument 0 will be the key and the argument one will be the value we know this part right so that is what we are setting over foreign and then what we'll do is for now although we are just implementing expiration but set also implements a lot of other functionality optional arguments so I'm just writing this Loop so that in future we would be able to accommodate those requirements right but the idea is for now we just have to support basic expiration which is starts with e x a capital X or a small e x this is what we would want to start with so now given that this is an optional argument it is very much possible that some like people would just pass set key and value they would not pass in expiration which means that our Loop when it starts with 2 it is very much possible that your length of RS is itself too and this Loop would not even execute so that's fine that is where we are having a default value and as we saw the default value of expiration is -1 because I'm setting something and if I'm not passing in expiration it is said to never which means that your key is never expired so that's why I'm setting the value to -1 which is a special value that denotes the T that this key should never be expired okay now what I'm doing is I got the key and the value now everything else are optional arguments so to extract those I am hydrating through all the r starting from the index two so 0 and 1 is key at the value and starting from 2 I'm checking if it is X or something X or basically something else so if I put a switch case if it's e x or capital E X or small e x which means that user has passed in some expiry while firing that command so with expiry what I would want to do is move forward and whatever is passed next to expiring is the time is the duration after which the key should be expired right that's a TTL so I'm doing an i plus and I'm just making an extra check in case user has not passed that extra argument like after ex if user has not passed anything which means that that's a syntax error we saw it in the edge case and if there is anything whatever user is causing it needs to be an integer a 64-bit integer if it is not an integer which means that value it is out of range which is what we saw when we passed in string in the argument so expiration and some random string when we passed it this is that extra check and if it is if all is good and we end the user with expiration passed a valid integer we would get X duration seconds which means that uh that the duration after which expiry should happen in seconds so if user sends in 5 we would be storing or we would be getting 5 over here and then what do we do is we Define a variable because for us when we are creating or we are storing this key value in our hash table where we would be storing it we would want to store we want to associate an expiry with that and now this expiry the granularity that we would operate in is a millisecond granularity so even if we get in second we would store it in milliseconds so that is when I'm just doing this duration multiplying by 1000 and I'm just storing this and I'm just preparing this duration to be that right so this is the expiration duration so if user passed in 5 I'll be getting 5000 in expiration duration milliseconds right and if no e x is passed this would not execute and all good right and in case user passes an argument which we don't support yet we don't support PX or NX up until now so which means that would be returning syntax error right so now that after this thing we would have key and value definitely set and X duration millisecond could be anything or rather it is optional the default value is -1 or it could be anything that user passes as a valid integer and then what we are doing is we are creating a new object now this is where we would have to do what create a custom object a custom class sort of thing a custom struct so the role of that would be so I created a file called store. go this store file is responsible for holding anything and everything in our

### Segment 3 (10:00 - 15:00) [10:00]

radius implementation now this store. go file is basically what a radius is simple key value store to hold key value the best data structure is a hash table so we are just using a map of string to Star object now this object is something that we have defined what this object says this object holds two things for now the first is a value which is an interface which means we can put in literally any value any data structure in this and it would work just fine so because object within which you are storing value this could be anything that is why we have given a type as interface and the second parameter is expires at now this expires sat is not storing the duration but it would store the absolute time at which your object will be expired so for example if right now the time is 5 PM some Epoch millisecond if I take in and if I pass in 5 Second as my TTL so I would be storing that absolute time at which it needs to be expired right rather than storing just five I would be storing the absolute time so basically five seconds past five is what I would be storing over here as part of epoch Middle East right okay so when this file loads I'm just creating a map over here which is which will which we are calling it as a store and the new object this new object is what this function is doing is this function is creating a new object setting with all the default values that we would want and it will be returning a reference to that object so it would accept a value and a duration and an expiration duration if tomorrow we add more functionalities to that we can just pass it over here the plan is that because we would want to store an absolute expiration time rather than duration we don't want to repeat the same logic at hundreds of other places so that's why this function call would help us keep this one logic at this one place only so what we would do is in case we are given duration milliseconds over here we are calculating the absolute expiry at so absolute expires at starts at -1 in case some duration millisecond is passed then we are taking time. now. unixmillis plus duration milliseconds because from that function also we'll get it in millisecond here also we are taking it in millisecond we are just adding it so we would get an absolute expiration time for this particular value right we are just creating a new object and we are returning a reference of it this is what the new object function would do right and apart from that what's the next step now that we have created a new object we are invoking put on it this put is also part of the uh the store. go file whose job is to add it to this hash map now I've created a separate function for this because tomorrow we might have multiple hash Maps rather than just one due to some implementation if to like in order to support a specific kind of implementation so that's why just to keep things extensible for the future just be Future Ready on that what we are doing over here is we are primarily storing the put function it's just an abstract function whose job is to take a key and an object not a value but an object and then make an entry in the hash map in the hash table that we have store of k equal to offset that's it and the second is get where given a key it returns a reference to this object and it just returns store of K if the value does not exist or sorry if the key does not exist in the hash map it will return a nil which is exactly what we want right this is how our store. go file would look like so now coming back to the set implementation we created an object and we put it in the hash table in the hash map that we have for a key for this object make an entry and when the entry is done we are returning to the client what an okay reply is a simple string so it is like here it is already encoded plus OK slash r slash n so without redoing the okay thing or without redoing the encoding again I'm just hard coding it that Send Plus OK slash r slash n and done so this is how our set limitation would look like right okay so we talked about set now let's talk about get what do we get so in get the argument there will there has to be exactly one argument which is the key if it is no argument is given or more than one argument is given that is an error so that is what we check over here and then the first argument that we are given is the key then what do we do is we invoke get on our store to get the key we would get an object reference if the object is nil we return a response or a resp nil which is a ready serialization protocol encoded nil now this nil response if you remember uh when we were discussing uh resp specification a nil is nothing but a string with the minus 1 length right this is what we are doing so that we don't have to write this nil again and again we have just created a constant

### Segment 4 (15:00 - 20:00) [15:00]

object out of it and we are just referencing it everywhere so if the object does not exist in get we would return nil which is what we are doing over here and in case the object exist in the hash map or in the hash table and its expiration is set so which means if object. expires that is something it is not minus on it some expiration is set I check if object dot expires is less than time dot now dot millisecond which means if the object exists in the hash map but it is expired I would return a nil again because if the object is all if object is already expired it does not make sense for me to return it right because X smart objects for your end user for your client an expired key is same as deleted key right so that is where what we are doing is we are returning nil over here in case your there is no expiration set or in case your expiration is yet to reach that's why what we are doing is we are returning the value but in an resp encoded form right so whatever the value is if it's string we would return string in most cases it would be string that's what it handles so we are taking the value we are encoding it and we are sending it back right and this is what our get implementation would look like right so and now the final implementation the TTL so what TTL does is TTL Returns the time to live of an object so from the current time how many seconds are left for the key to be expired so it also expects exactly one argument which is the key if that argument is not given that's in syntax error and my bad instead of get this has to be TTL okay for the detail command and key we are setting arcs of 0 to be the key and I am doing a normal get on the store will get an object reference if this object references nil which means we have to return minus two remember if object does not exist or sorry the key does not exist and we fired TTL on that we got minus two if the key exists but its expiration is not set then we return -1 this is what we are doing if object would expire double equal to minus 1 we would return minus 1 over here right and because it is an integer it starts with a colon -1 slash r slash n and resp encoded integer and in case some expiration is set then what do we do is we compute the TTL the we compute the duration left in millisecond would be object. expire set because here we are storing everything in millisecond minus my current time my current Epoch millisecond the difference would be the number of milliseconds left and then if it is less than zero this is the final check that we are making in case I am getting an object which is already expired which means yet to be deleted but expired if duration is less than 0 I am returning minus to minus 2 implies that of that key does not exist which is exactly what we want because the object is already expired while we were doing this if object is expired return minus 2. and in case that is not there is enough duration left then what do we do is we convert this millisecond into second convert it into an integer and encode it and when we encode this we are doing a normal resp encoded integer over here and returning the response this way when our client invokes a TTL command to our server for a particular key it would get in return the number of seconds left for the key to be expired and just a hunch just the final file that we touched upon is the encode in encode up until now we only implemented string type but now we Implement one more type in 64. now for in 64 we know about RDS main coding of an integer looks like RSP encoding of an integer starts with a colon followed by a string representation of an integer so for example if I am storing value 1000 it will show one zero and Then followed by slash n so which is exactly how I am returning I'm encoding it and converting it into bytes and returning now this is exactly what we would be returning as part of the response which is where on the radius CLI you would see that we are indeed getting an integer minus 2 in the response and these are all the files that we would have to change and this is how the code would be structured for get set and TTL let's just quickly go through and see a quick demonstration of it so I'm running my own server on Goran main. go it is running on Port 7379 so through redis CLI dot slash red is CLI minus P 7379 so here are ready CLI is now connected to our server now if I do set space k comma V it's written okay a simple string if I do get K it returns me V it double quotes which is a bulk string now if I do TTL of K because expiration is not set we would get minus 1. now let's say

### Segment 5 (20:00 - 22:00) [20:00]

I do set K comma B with expiration of 10. and if I do oh syntax error great catch e x and then 10. so which means that we are setting a key K with value V expiration 10 if I do get K we would get the this thing the value V and if I do ttlk oh we just missed okay let me just do it again set K and expiration to 10 let me check TTL 9 7 6. four I'm just waiting for a random tank one zero and then minus two because a key is expired the same as key does not exist so we would be returning minus so it's not like ever didn't decreasing beyond that because key does not exist anymore we are returning minus two right and this is exactly what how ready CLI or redis client also does we have just re-implemented get set and TTL up until now right okay so that is it for this one but there is a great thing to be implemented what would we Implement next now here if you see here we added a lot of stuff but here although we are telling our client that key does not exist or key is expired with us because of which we are returning minus two if you look at closely we have not implemented delete yet we although we say that key is expired but we are never explicitly deleting a key so how would that happen so in the next video right in the next part of this thing what we would be doing is we would be looking at how to expire a key how keys are expired in radius how we would write so we would be implementing delete command and Ka function right so that is the agenda or that's going to be the agenda for the next video so I hope you found this amusing I would highly highly encourage you to implement this entire source code is present at github. com check out the fifth commit from the beginning to see this exact changes in place right so yeah that is it for this one I hope you liked it and I'll see you in the next one thanks
