Adding a cache is not as simple as it may seem...

  Рет қаралды 102,741

Dreams of Code

Dreams of Code

Күн бұрын

Knowing what the expect and how to mitigate the issues with caching is the first step towards a successful caching implementation.
Adding a cache is usually a good way to reduce load on your database, but it does come at the cost of increased complexity. This video looks at the most commong caching pattern, and the problems that can occur.
This video was sponsored by Aiven. Their platform is used in the video for a free tier of Redis and PostgreSQL.
To get your own free Redis and PostgreSQL instance, sign up at go.aiven.io/dreamsofcode
#postgres #redis #caching
GitHub Project:
github.com/dreamsofcode-io/sp...
The information in this video is found in this whitepaper by AWS.
docs.aws.amazon.com/whitepape...
Become a better developer in 4 minutes: bit.ly/45C7a29 👈
Join this channel to get access to perks:
/ @dreamsofcode
Join Discord: / discord
Join Twitter: / dreamsofcode_io
00:00:00 Intro
00:00:35 Cache Aside
00:01:01 Implementation
00:06:52 Cache Invalidation
00:07:28 Eviction Policy
00:09:15 Key Expiration
00:10:37 Write-Through Caching
00:12:49 Outro

Пікірлер: 213
@dreamsofcode
@dreamsofcode 2 ай бұрын
Big shout out to everyone in the comments on this video for asking GREAT questions
@user-jb4pt2or2j
@user-jb4pt2or2j 15 күн бұрын
Can you share your neovim distro?
@dreamsofcode
@dreamsofcode 15 күн бұрын
@@user-jb4pt2or2j you can find it on GitHub at elliottminns/dotfiles
@nathaaaaaa
@nathaaaaaa 2 ай бұрын
Usually instead of write-through, I just DEL the relevant keys and force a new cache miss. Looks very reliable to me
@dreamsofcode
@dreamsofcode 2 ай бұрын
That's a cool idea. I imagine it makes things a little more simple and can work for more advanced aggregations! I like it!
@xorlop
@xorlop 2 ай бұрын
lol just left long winded comment about this
@dreamsofcode
@dreamsofcode 2 ай бұрын
​@@xorlop I'm glad you did!
@daleryanaldover6545
@daleryanaldover6545 2 ай бұрын
I would do the same 😊
@123mrfarid
@123mrfarid 2 ай бұрын
Good idea. Thank you..
@o11k
@o11k 2 ай бұрын
"There are only two hard things in Computer Science: cache invalidation and naming things" ~Phil Karlton
@hansenchrisw
@hansenchrisw 2 ай бұрын
And off by one errors 😉
@Rundik
@Rundik 2 ай бұрын
And cache invalidation
@tacticalassaultanteater9678
@tacticalassaultanteater9678 2 ай бұрын
​@@hansenchriswand scope bloat
@af43bacc
@af43bacc 2 ай бұрын
Concurrency and floating bugs: "Am I a joke for you?"
@markhaus
@markhaus Ай бұрын
@@Rundik and cache invalidation
@xorlop
@xorlop 2 ай бұрын
What a cool video! So many great ideas. Another idea for write through cache: delete the key instead! I think this could be good because whenever you update the entry, you are resetting its LRU value, which might not be accurate/helpful. I think there are a few cases where db write is not aligned with access of the key from cache. What if user writes spell but doesn’t use it right away, for example? By deleting it, you are saying save is not the same as use, which might be better aligned for a spell store. Newly updated spells might not be so popular. It also helps minimize cache overall size, which probably helps the redis LRU algorithm, which is only approximate LRU.
@dreamsofcode
@dreamsofcode 2 ай бұрын
This is a great idea! Deleting does make a lot of sense when it comes to fast accessed data. I think the time you'd want to use write through would be when the data itself takes a long time to populate. But even then, you'd likely use some sort of expiration/deletion based resync. Another approach would be to not extend the expiration which I believe you can do with another redis SET option.
@daleryanaldover6545
@daleryanaldover6545 2 ай бұрын
yes, the principle is delete cache on every operation except get requests, that's where we store the cache!
@Cranked1
@Cranked1 2 ай бұрын
Making the writing to the cache independent of the completion of the request can be dangerous because if writing to the cache fails, you have a big problem. It also could happen that the user already moves on to make another request before the cache was written in the previous request which results in wrong data. This can be completely inconsistent and you have no gurantees (e.g. like database ACID). Even a database transaction won't save you because the system can still fail between cache write and transaction commit.
@dreamsofcode
@dreamsofcode 2 ай бұрын
Yep, 100%. In a distributed system, this is even more challenging as you'd likely need to lock the key in the cache as well, which is even more complexity.
@DryBones111
@DryBones111 Ай бұрын
@@dreamsofcode Eventual consistency is both a blessing and a curse. Just like how async colours your functions, eventual consistency colours your whole system.
@nedimkulovac6394
@nedimkulovac6394 Ай бұрын
Man, this video is awesome. By far the best and clearest explanation I've come across. Thanks a ton! I would like to see more videos explaining cache strategies and when to use caching and when not to use it.
@rodemka
@rodemka Ай бұрын
Video checklist: ✓ Editor - Neovim ✓ DB - PostgreSQL ✓ Cache - Redis ✓ gRPC - Fulltext seraches: meilisearch/sonic/typesense and postgres tsvector/tsquery - Authentication and authorization - oauth2, saml, openid, jwt, etc. endless list - full axum course from "todo app" -> "url shortener app" -> "pocketbase like app" - templates engines + hype about htmx - reports from db - rust/go + db -> pdf creation Thank you for the inspiring high quality videos!
@dreamsofcode
@dreamsofcode Ай бұрын
Thank you for the great suggestions!
@posteisnoob5763
@posteisnoob5763 Ай бұрын
Thanks for the great video!! I would really like to see your take on when / when not to cache
@Biowulf21
@Biowulf21 2 ай бұрын
Love your videos man. Keep it up!
@thienlacho860
@thienlacho860 Ай бұрын
With write through, you may face dual write problem. There maybe a success write to database, but a timeout in Redis call. In that case, there is a stale data still in redis. In my application, I use Debezium to capture the change in the database and Produce to a Kafka topic, then a background process consume those changes and apply a cache invalidation. In my opinion, cache delete is safer than change the cache, as one cache may be affected by many different action, and those action may come concurrently, if you change the cache in wrong order due to async, then the cache may be changed to wrong result. Just delete the key for safe and memory efficiency.
@dreamsofcode
@dreamsofcode Ай бұрын
Debezium is pretty great. I wanted to showcase it in this video but it blew the scope out way too much! CDC caching is dope.
@penguindrummaster
@penguindrummaster 2 ай бұрын
I like the final takeaway saying caching is not your first step, and that database optimization should always be a consideration. I've seen too many people complicate their tech stacks just to avoid tackling an otherwise simple problem. Much like C, just because SQL is old doesn't mean it isn't really good at certain tasks.
@ThatGuyJamal
@ThatGuyJamal 2 ай бұрын
Learned a lot about caching! Thanks for the video
@dreamsofcode
@dreamsofcode 2 ай бұрын
I'm glad it was educational!
@legobuildingsrewiew7538
@legobuildingsrewiew7538 Ай бұрын
Instantly subscribed! Great video.
@marcing5380
@marcing5380 2 ай бұрын
One major thing to remember about caching and caches (or in general where you have two separate sources of truth/data) is that you'll always run into eventual consistency so you shouldn't use it in every possible scenario. I.e. there is a non-zero time for the cache and DB to sync up in which the data is inconsistent but still readable. The only to avoid is I think explicit locking but that slows down the whole thing quite considerably - when you make an update to a table you lock everything related to it and unlock after the write and cache update have been completed.
@petar567
@petar567 2 ай бұрын
Great video. Thanks for the information, also I would appreciate it if you make a video of when to use cache and when not.
@underflowexception
@underflowexception 2 ай бұрын
if you're using PHP and Laravel you can use the dispatchAfterRequest function to save to cache
@amolgupta8077
@amolgupta8077 2 ай бұрын
yes
@WanderingCrow
@WanderingCrow 2 ай бұрын
Great video, very clear and articulated! Cache is among my biggest weakness, I think, after authentication and token management, so I'd be interested to learn more about them, and how/when to use them effectively 🤔
@dreamsofcode
@dreamsofcode 2 ай бұрын
Thank you! They definitely have their use cases, but they're not that simple to implement and there's a lot to consider, more so that I even do in the video!
@GreatTaiwan
@GreatTaiwan 2 ай бұрын
external IDP with SAML2 & OIDC (PKCE) is my biggest weakness
@SeanLazer
@SeanLazer 2 ай бұрын
My advice is squeeze as much perf as you can out of your primary data store before you add a caching layer! Your RDBMS can take you a lot further than some people realize.
@EvanEdwards
@EvanEdwards Ай бұрын
Best walk in on a codebase I ever did was to realize they had left on passthough on their cache layer. The cache was invalidated with every request and passed through, presumably as a debug/development one line shortcircuit. I pointed it out, they deleted the one line and vastly improved responsiveness. They were nearly three months post-launch. (I was working on a loosely coupled service; consulting company operating as a separate department, essentially. I found it when looking into connecting to their database for some features).
@skr-kute1677
@skr-kute1677 Ай бұрын
Thanks for the vid Informative and simple
@Sarwaan001
@Sarwaan001 Ай бұрын
I work at a team that handles very large amounts of data and we usually take a “best tool for the job approach”. E.g. for a graph database as the ground truth, we use it for simple queries that are O(1) use a search db for search at O(log(n)) and use a trigger to send data from the graph database, obtain the full object by performing a walk, sending the object to a search db. Feel like this is technically like caching but it’s still very fast and we think of cache databases more of a crutch to by more time rather than a solution.
@zshanahmad2669
@zshanahmad2669 2 ай бұрын
great video. my biggest problem with caches in bigger projects is dealing with related data. for example, I cached the blogs api: GET blogs/blog_ID, this api returns the JSON which has blog and the information about the author. When the data about author changes e.g. their name, I have to invalidate the blogs/blog_ID too, otherwise users will get the old author data. I know I could only return the blog data in blogs/blog_ID request, but I cant change the frontend, which expects the user data inside of the response.
@wcrb15
@wcrb15 2 ай бұрын
Too many people reach for caching as a mechanism to improve performance when actual performance tuning of thr application is the more appropriate action. Cache isnt going to save you if uou application is over fetching or inefficiently grabbing data from the DB. But wjem it's used correctly caching is awesome!
@n0kodoko143
@n0kodoko143 2 ай бұрын
awesome video. I would love to see a 'when to and not to cache' video.
@dreamsofcode
@dreamsofcode 2 ай бұрын
Thank you! I shall do one then! 😁
@giuliopimenoff
@giuliopimenoff 2 ай бұрын
I just removed the Redis cache for my project because I figured out it created more issues than benefits. Databases are already fast as heck, so use caches with intention. I use Redis for session tokens for example but nothing else rn
@dreamsofcode
@dreamsofcode 2 ай бұрын
I think this is right choice. Session tokens are a good use of caching.
@eveleynce
@eveleynce 2 ай бұрын
honestly I almost never use an external cache for anything I've written, because it helps me considerably more to consider how and WHY I want to cache information for each particular type of data. Some of it never needs a cache at all, and some of it only needs to cache a few bits of data, and it also gives you a hint on how to tell when your cache is stale since you know exactly what you're caching and when, rather than caching all data all the time
@giuliopimenoff
@giuliopimenoff 2 ай бұрын
also when data is relational caching just triplicates the effort to keep it synced properly
@anthonycavagne4880
@anthonycavagne4880 2 ай бұрын
I don't exactly understand you store the userId as the key and the token as the value ? Why is this better than using cookie ?
@giuliopimenoff
@giuliopimenoff 2 ай бұрын
@@anthonycavagne4880 I use cookies and in the cookie I store the session id. Then in redis I have an hashmap with the user id and session id, so I can get the session data quickly and can also invalidate all sessions if needed
@allroni
@allroni 2 ай бұрын
Great video, as usual! 🙂
@kennedydre8074
@kennedydre8074 2 ай бұрын
I would really love to see a video of when to cache and when not to cache, thank you.
@hunorportik5618
@hunorportik5618 Ай бұрын
Useful info, well described. One important thing was left out IMO: using concurrency might actually re-introduce the stale-data-issue since one might fail due to a non-transient (or improperly handled transient) issue.
@dreamsofcode
@dreamsofcode Ай бұрын
That's correct! This issue becomes even more problematic in a distributed system as well if we horizontally scale our app.
@yuu-kun3461
@yuu-kun3461 2 ай бұрын
After watching the recent PostgreSQL video by "The Art Of The terminal" it would seem to me that adding Reddis to PostgreSQL is not needed for most projects. Additionally, as presented in the blog post by martinheinz, a cache can be achieved by creaing UNLOGGED tables. And if the key-value pair functionality of Reddis is that important, the video mentioned covers that too.
@dreamsofcode
@dreamsofcode 2 ай бұрын
100% agree. Most use cases it's not needed. And the complexity can often outweigh the benefit. I don't know if I would consider UNLOGGED tables a viable alternative. I did some benchmarking on them for another video I had planned and they're no where near as fast. There's also a lot of caveats with using them and if you're unaware it's unlogged, mistakes can happen.
@peppybocan
@peppybocan 2 ай бұрын
I think Redis is more perfomant than Postgres' unlogged tables, just because Redis a specific tool optimized for in-memory store. Postgres, OTOH, has layers of abstraction for a simple store and retrieve functionality. Use correct tools for the correct uses.
@DanniDuck
@DanniDuck 2 ай бұрын
@@dreamsofcode *The complexity often does not outweigh the benefit. It's extremely simple and will make everything 100x faster. For example, say you have a bunch of base64 encoded images stored in pg, you can make it so the image (likely ~10 kb each or so), gets stored in memory as it's result format, allowing you to make anything involving images significantly faster. It can make things super fast if you use it right, eg. big queries for a product's info or whatever.
@OneShore
@OneShore Ай бұрын
@@peppybocan Yeah, the difference is that Redis is very lightweight. If you're looking to throw more RAM & CPU at a DB problem, then Redis starts to make sense. Because 8GB Redis + 8GB Postgres is going to outperform 32GB Postgres in many cases.
@peppybocan
@peppybocan Ай бұрын
not necessarily, depends on the workload. If you have a transaction-heavy processing, there is no way around it. E.g. if you are a paypal and you need strong ACID guarantees you may find yourself in a pickle. Storing payment information in-memory is fine as long as you have resiliency built into the application.@@OneShore
@fahimferdous1641
@fahimferdous1641 2 ай бұрын
I legit thought today's sponsor was docker XD Are you using the embedded terminal though?
@mementomori8856
@mementomori8856 2 ай бұрын
crazy that you release this the same day as I start implementing Redis from scratch
@alirahimi4477
@alirahimi4477 2 ай бұрын
Most of the time that one select by id isnt the bottleneck, rather it is a complex query that returns a possibly big result and caching that can be a real pain or plainly impossible. When you query by X but update by Y there is no clear way to use the write through method to update your cache because you dont even know what cache keys you should be updating!
@dreamsofcode
@dreamsofcode 2 ай бұрын
Yep, you're correct! Apologies if I didn't make that clear in the video, I didn't want to complicate the caching implementation itself so went for a simple query
@RomanKornev
@RomanKornev 2 ай бұрын
In the Write-Through caching case, what happens when the concurrent cache write takes slightly longer than expected? Now the client assumes that the data was updated, but when reading it back it would be a race condition, and the value might be stale.
@dreamsofcode
@dreamsofcode 2 ай бұрын
Your correct, that's one drawback of concurrency as it can introduce a race condition. The only way to solve it would be to lock the cache and pass that lock through to the concurrent task. The other approach is to do write through caching with the cache being the first target, although this can lead to some weird state if the database operation fails. Either way adds complexity!
@tiagocerqueira9459
@tiagocerqueira9459 2 ай бұрын
I was thinking something similar, like the DB or the cache fails, you need a way to sync the state again. I think the easiest solution is to spawn 2 tasks, one for the DB and one for the cache and await the results of both and handle those cases. However, the response time is the slowest of the two
@dreamsofcode
@dreamsofcode 2 ай бұрын
@@tiagocerqueira9459Even spawning two tasks can be complicated, however, especially if one fails and the other doesn't. You need to then reconcile afterwards.
@tiagocerqueira9459
@tiagocerqueira9459 2 ай бұрын
@@dreamsofcode yes, but I guess you always need to wait for the result of both in the handler when you mutate data, you can't just "set and forget" as an optimization
@EduarteBDO
@EduarteBDO Ай бұрын
I think one solution workflow would be: lock cache key > update database > (update failed > unlock cache) update success > delete cache and let a cache miss happen in the future.
@michaelhenze877
@michaelhenze877 Ай бұрын
Would really like to see a comparison between NvChad and your current NeoVim configs.
@rando521
@rando521 2 ай бұрын
so i have a question since i am new to rust and axum the appstate is some amalgamation of arc/mutex and you lock it everytime you want to access db or redis cache wouldnt this just mean you are making the asynchronous runtime semi-synchronous
@dreamsofcode
@dreamsofcode 2 ай бұрын
It's a great question. My implementation in the video is naive, mainly due to simplifying the code as much as possible. The requests are still asynchronous but you're correct the lock would prevent concurrent requests both accessing the shared state. An improved implementation would be to use either a RW lock, or have a better abstraction of the state to only lock when needed (rather than at the start of the request)
@rando521
@rando521 2 ай бұрын
thanks kinda new to rust and async
@animanaut
@animanaut 2 ай бұрын
if you want to enable client side caching there are also etag request/response headers that can be used as well. a whole other topic, but i believe they use hashes to let the backend decide to respond with either a potential big payload over the network or not if the client's hash code looks ok to what is pesent in the server db/cache already (returning http code 304 instead).
@hansenchrisw
@hansenchrisw 2 ай бұрын
+1, though If-Modified-Since is a bit simpler and usually sufficient
@CesarLP96
@CesarLP96 2 ай бұрын
where can I find more of this topic?
@hansenchrisw
@hansenchrisw 2 ай бұрын
@@CesarLP96 search for HTTP conditional requests
@animanaut
@animanaut 2 ай бұрын
developer pages from mozilla would be one recommendation from me, also known as mdn
@animanaut
@animanaut 2 ай бұрын
@@CesarLP96 mozilla developer pages would be one page, just search for etag
@hosamhamdy258
@hosamhamdy258 2 ай бұрын
great video can you make when to cache or not video too thanks in advance
@kartik180rajesh1
@kartik180rajesh1 Ай бұрын
If you use the redis as a cloud hosting service isn't it defeating the purpose of the cache? The cache should be ideally as close to your backend service - either in your network or same instance memory
@LauriePoulter
@LauriePoulter Ай бұрын
any tips for avoiding stale data when dealing with a 3rd party service that can be updated by other actors?
@frazuppi4897
@frazuppi4897 2 ай бұрын
amazing video, will checkout aiven for sure
@arcadierosca9818
@arcadierosca9818 2 ай бұрын
Can you create a video on how to make video like that? it's amazing!!!
@vinii2815
@vinii2815 2 ай бұрын
hey sorry this is out of the topic of the video but will you make a new video about NvChad configuration? their new file structure is very confusing and I haven't seen anyone with an update tutorial for it yet
@dreamsofcode
@dreamsofcode 2 ай бұрын
I'll be redoing the neovim content soon! I recommend staying with NVChad 2.0 for the mean time!
@PiesekLeszek90
@PiesekLeszek90 2 ай бұрын
Write-through cache sounds like you just have 2 databases running at the same time, but I assume it's because of the simplicity of the example? I'd imagine you only cache the prepared API response with all it's relations and after applying logic, and not "raw data" as it is in the main database? This doesn't sound too optimal when you update one record that applies to many users, but each user needs it's own cached version?
@TheTwober
@TheTwober 2 ай бұрын
Now imagine you program in Java and all those problems are already solved. :) Just use a SoftReference that will be cleared by the GC if it needs memory, and the attached ReferenceQueue can be (blockingly) polled by a background thread, so your cache gets informed whenever something got removed by the GC. A near perfect cache is nowaydays literally 3 lines of code in Java.
@archip8021
@archip8021 2 ай бұрын
i have a table of about ~20 items that i need very, very often, and it rarely changes is this a good use case for caching? can a whole table be cached like this?
@dreamsofcode
@dreamsofcode 2 ай бұрын
I think for that size, you're likely not going to need caching. Caching is more for when you have slower queries, such as aggregations or hitting an API that has poor performance. Adding in a cache adds in complexity and it's probably not worth the performance gain you might receive.
@arturpendrag0n270
@arturpendrag0n270 2 ай бұрын
Cant you load them at the start of the request and use some singleton or put them in some "global" variable so you wont have to request the unless needed. Even if thats not the case the db usually has caching mechanisms for repeating queries so for such small size of records its probably unnecessary.
@Fanaro
@Fanaro 2 ай бұрын
Please make a video on how you edit your videos!
@watzyh
@watzyh Ай бұрын
I never use redis for caching. It's a database. Other than simple key-value store, i use it for handling time dimension in the program (rate-limiting task & job queue) very useful for webserver which each request run separately. For caching, it's job for webserver like nginx. It's far-far more efficient & performant. I never have any issue with cache invalidation or using custom cache-key. You can control nginx cache programmatically just like redis cache.
@Avanta1
@Avanta1 2 ай бұрын
I'm not very familiar with async Rust, but is there any change of race condition when updating the cache? If a thread that was spawned later acquires the lock before an earlier spawned thread?
@dreamsofcode
@dreamsofcode 2 ай бұрын
Youre correct.There absolutely is a chance. A race condition is introduced by making the update concurrent from the response. If you want to ensure 100% consistency then performing the update synchronously would be preferable!
@Avanta1
@Avanta1 2 ай бұрын
@@dreamsofcode Cool, thanks for replying!
@dreamsofcode
@dreamsofcode 2 ай бұрын
@@Avanta1Thanks for asking the question!
@CrypticConsole
@CrypticConsole 2 ай бұрын
Why do you need to cache this in Redis? Could you not just use master slave database scaling for read heavy workloads?
@dreamsofcode
@dreamsofcode 2 ай бұрын
Read replication is a decent solution in many use cases, especially read heavy as you mentioned. Just like caching, it's a tradeoff so it does depending on what your data model / system looks like.
@saywaify
@saywaify 2 ай бұрын
Can you please share your nvim setup (or at least the colorscheme) ?? It looks so fine
@perz1val
@perz1val 2 ай бұрын
Colorscheme looks like catpuccin
@user-oo9el8sx5b
@user-oo9el8sx5b 20 күн бұрын
what video editing software do you use? it looks like you're on Linux
@Amejonah
@Amejonah 2 ай бұрын
There is one big question I have for a long time: how do distributed microservices work? Especially how scaling of certain services can be achieved? How buses/message broker play a role in it? You might be the one who can address these questions using simpler terms.
@betoharres
@betoharres 2 ай бұрын
why did you make the Write Through Cache concurrent? there's a chance of two concurrent requests have a mismatch value returned based on what's in the database; maybe I'm missing something here
@dreamsofcode
@dreamsofcode 2 ай бұрын
You're correct. However, even with it being serial, there's no guarantee in a distributed / horizontally scaled system of a race condition not occuring. With a cache, it's almost impossible to guarantee consistency without locking the actual cache itself. In a distributed system, that's going to be even more complex.
@neelg7057
@neelg7057 2 ай бұрын
Which font is that in your nvim? :)
@fahimferdous1641
@fahimferdous1641 2 ай бұрын
What would be an example usecase for the random eviction policy?
@I25mI25
@I25mI25 2 ай бұрын
LRU comes with a small overhead since you have to somehow store/maintain a "list" of which items were last accessed. In many "normal" cases, it is likely that an item that was recently accessed will be accessed again, so keeping the newer/most frequently used ones in cache is worth the overhead. If your access patterns on the other hand are mostly random, keeping track of usage patterns isn't really worth it, so you can just delete any random entry. You might still want to use a cache even in random use cases when the occasional random cache hit might still give a big enough boost/save you money in bandwidth/storage access cost to make the added complexity of a cache worth it.
@dreamsofcode
@dreamsofcode 2 ай бұрын
This is a great explanation. As for specific use cases, it's hard to really describe any that would fall into this. But any data / queries that have no discernable pattern, or in a system where the likelihood of needing a key is the same across your data set.
@egemengol306
@egemengol306 2 ай бұрын
For the life of me I don't understand the need for Redis When I need caching I always reach for in-memory caching libraries right in my codebase, reducing latency with development and deployment complexity at the same time, while staying featureful. If the language is memory hungry in-memory sqlite works really well for most of the cases If I want centralized state I reach for the database itself, Postgres is excellent Under which circumstances Redis would be the first choice? Edit 1: Multiple instances caching for mutable data would be one I suppose
@IS2511_watcher
@IS2511_watcher 2 ай бұрын
4:26 `.unwrap_or(None)` can be shortened to `.ok()` for `Result`, more idiomatic too.
@TR1XT3RZ360
@TR1XT3RZ360 Ай бұрын
can you share your terminal setup.
@JuanPabloCisneros2207
@JuanPabloCisneros2207 2 ай бұрын
Caching is always tricky. In the lazy loading presented, you can end hitting the dual write problem as postgres is wat slower than redis. If the system needs concurrency it could be a tricky bug to solve i think
@Affax
@Affax Ай бұрын
Welp, time to move to KeyDB or DragonflyDB, at least they both are redis API compatible haha
@Cal97g
@Cal97g Ай бұрын
It’s not stale it’s just eventually consistent
@nexovec
@nexovec 2 ай бұрын
I just realize you can literally ship a product that's just static files and a Postgres server. Curb your stack, please.
@krateskim4169
@krateskim4169 2 ай бұрын
I would like to know when to cache and when not to please
@fadhilinjagi1090
@fadhilinjagi1090 Ай бұрын
What of you deleted the cache entry right before you updated/deleted the record in the DB? Will this prevent the race condition?
@fadhilinjagi1090
@fadhilinjagi1090 Ай бұрын
I think that's optimistic mutation, if I'm not wrong.
@Zutraxi
@Zutraxi 14 күн бұрын
Don't forget the retry policy for when your concurrent write to the cache fails. What if the api crash as the write is happening. Better use a fault handling outbox pattern. Suddenly caching is slower than accessing the database.
@SlavomirDanas
@SlavomirDanas 2 ай бұрын
Woah, wouah, woah! Just 8 seconds into the video and I see inforgraphics with cache layer in the completely wrong spot.
@pieter5466
@pieter5466 2 ай бұрын
8:14 Makes you wonder whether there is *ever* a good use case for "random order"
@ivan_adamovich
@ivan_adamovich Ай бұрын
I did not understand one thing: 50 ms is certainly good response time. but for the simplest api written in rust, there is somehow a lot, don't you think? (i use go im projects, so i'm noob in rust)
@illyias
@illyias Ай бұрын
You won't need caching in a simple project, your database will be able to handle the load fine.
@ebukaume
@ebukaume Ай бұрын
What happens when the spawned task compeletes with an error? It seems we didn't completely solve the stale data problem.
@dreamsofcode
@dreamsofcode Ай бұрын
Correct, and in a distributed system, this is even more difficult!
@peppybocan
@peppybocan 2 ай бұрын
Unless you handle 1000s of concurrent users and they pay you nothing (free users) you don't need to worry about caches. The right DB design with the right sized DB node can handle 1000s of concurrent users. Once you start handling 10k-s of users, then you think about the caching, but at that point, it should be fairly easy to scale the particular parts of your DB, because you *know* what is slow.
@dreamsofcode
@dreamsofcode 2 ай бұрын
100% Profiling your queries and using well placed indexes is always a better option. Sometimes it's not possible (such as hitting a remote AP)I, but if you have control of the database then it's always the better option
@parkourbee2
@parkourbee2 2 ай бұрын
Even then, do I really need a cache? Why not just index what needs to be indexed?
@peppybocan
@peppybocan 2 ай бұрын
yeah absolutely! Those limits are external, and that's when it matters. I think Redis is a viable option in that case. even things like session authentication can be done with a silly in-memory LRU cache and it will get you 90-95% to the goal. But people tend to be very quick to stuff the project with a billion dependencies. @@dreamsofcode
@dreamsofcode
@dreamsofcode 2 ай бұрын
@@parkourbee2If you don't have access to the database? I'm thinking more like Remote API's etc where you don't control the data at all. for example, we had an API that hit NIST for CVE's and was incredibly slow, in that case, caching was a good solution.
@luca4479
@luca4479 2 ай бұрын
Postgres has built-in caching which is already crazy performant
@PhilfreezeCH
@PhilfreezeCH 2 ай бұрын
Who ever thought caching was simple? Its one of those rare things thats hard on all levels. Its very difficult in hardware development, difficult in software and ridiculously difficult in networking, its just brutal. Plus it always requires a ridiculous amount of benchmarking and verification to make sure you don‘t accidentally degrade performance on certain workloads or even worse, mess up data.
@youtube_user9921
@youtube_user9921 2 ай бұрын
Hi. Can you also post tutorial lectures on nix?
@dreamsofcode
@dreamsofcode 2 ай бұрын
Absolutely! I'll likely do it on my other channel which is more focused on Linux and FOSS. I've been playing with NixOS more on there
@youtube_user9921
@youtube_user9921 2 ай бұрын
Can you tell me which channel it is?
@foreverexpanding
@foreverexpanding Ай бұрын
Why not update the cache when we update the DB, in that case there would be no need to worry about it being stale
@M3t4lstorm
@M3t4lstorm 2 ай бұрын
Note: In the write-through example, if your application crashes/errors/gets killed before the cache update is writen to redis (after the DB write) you will have stale data forever.
@dreamsofcode
@dreamsofcode 2 ай бұрын
You mean until the TTL?
@liu-river
@liu-river 2 ай бұрын
yeh, but if you do sync, update redis after successful dB write then you sacrifice speed. I guess you can implement some kind of rollback if either fails?
@ShimoriUta77
@ShimoriUta77 2 ай бұрын
Rust code is so beautiful.
@dreamsofcode
@dreamsofcode 2 ай бұрын
😅 It's not known for it's beauty
@backupmemories897
@backupmemories897 2 ай бұрын
sometimes adding cache slows it down xD but scale it better xD because whenever u do something u call that cache system.. another step.
@dreamsofcode
@dreamsofcode 2 ай бұрын
Absolutely! That's the problem in the case of inserts at first. It improved the performance of the reads on a cache hit, but caused the timings to increase by 66% on a cache miss.
@saxtant
@saxtant 2 ай бұрын
You do you your hardware is pretty much taking care of this already?
@ordinarygg
@ordinarygg 2 ай бұрын
90% of issues is missed indexes, or crappy backend code that runs 99% and 1% db time. So before you say DB is slow, please benchmark your API and DB independently. Simple 8 core Ryzen machine can handle 300k selects/sec and 60k/inserts per seconds using PostgreSQL. 256 cores and 1 TB of ram will solve a lot of issues in single instance. People don't even reach a level of vertical scaling first, instead starting scaling horizontally, huge mistake for middle-small businesses and startups.
@dreamsofcode
@dreamsofcode 2 ай бұрын
Yep, I agree with you (I believe I stated something similar at the end). There are certain use cases where caching applies, but in general, optimizing your database queries is the correct approach. There is a case for horizontal scaling over vertical still, especially wrt availability. But even then you can use read replication to improve that.
@kriffos
@kriffos 2 ай бұрын
If you want a really fast cache, it is a good idea to scale the cache together with your application and have no http request to the cache. Most of the time spent to get the data is probably http overhead. I think cache as micro service is - most of the time - a bad idea.
@theblckbird
@theblckbird 2 ай бұрын
In Rust, you can do the following to convert a Result to an Option: let my_result = action_that_returns_a_result(); // Result let as_option = my_result.ok(); // Option It works the other way around as well: let option = Some("foo"); // Option let as_result = option.ok_or(0); // Result let option = Some("foo"); // Option let as_result = option.ok_or_else(|| 3 * 3 / 9) // Result
@dreamsofcode
@dreamsofcode 2 ай бұрын
This is much simpler! Thank you.
@nathanoy_
@nathanoy_ 2 ай бұрын
Awesome write up. I was about to write a similar comment. Now I write this reply to push this one. 👌
@Maxelya
@Maxelya 2 ай бұрын
I still consider myself lacking experience with Rust, but somehow I knew about these "ok" methods and was about to point it out after watching the vid ^^'.
@FinlayDaG33k
@FinlayDaG33k 2 ай бұрын
There is a major issue tho... If your key expires, and suddenly 1K requests come in, you're now hitting the database with all 1K requests and may overload the database anyways. Not exactly ideal.
@dreamsofcode
@dreamsofcode 2 ай бұрын
You're correct, this is known as the thundering herd problem. You can solve this by using something such like a single flight mechanism or connection pooling, again it's more complexity though.
@mind.journey
@mind.journey 2 ай бұрын
I don't know if it's optimal, but what I usually do is never let the key expire, and instead just create a cronjob (or something similar) that periodically refreshes the key with updated data.
@FinlayDaG33k
@FinlayDaG33k 2 ай бұрын
@@mind.journey This works depending on the goals yes. If it's data that you know will be highly saught after by your code, it can definitely work. However, you are now burdened with the task of guessing which data would benefit from it. It can also lead to you having a lot of data in the cache that you may only need once under the full-moon, thus wasting resources in fetching and keeping it cached.
@Ca1vema
@Ca1vema 2 ай бұрын
Dunno what you're talking about, to add cache all I need is to put 2 lines in framework settings 🙃
@perz1val
@perz1val 2 ай бұрын
Looking at the comments I think you should've used a request that queries multiple tables of normalized data into a single object. Like /user/2/permissions is: user + user_role + role_permission + permission (list of permission names). Then the benefits are clear. Using cache to store a SELECT * FROM table; is a bad example.
@dreamsofcode
@dreamsofcode 2 ай бұрын
Yeah, that's fair. I wanted to keep the interface as simple as possible so as not to distract from the caching itself. My original setup was doing a string search across 10m rows, but then it added more complexity to the examples (and at that point and index is still a better solution).
@CottidaeSEA
@CottidaeSEA 2 ай бұрын
Cache is all fun and games until the cache is automatically invalidated due to a timer and everyone hits the same slow query at the same time.
@dreamsofcode
@dreamsofcode 2 ай бұрын
This is a good one! The thundering herd problem. There are ways to solve it, using something such as single flight, although again it adds more complexity. Much harder to solve across in a distributed system. I'll probably do a video on it as a few people have mentioned it!
@CottidaeSEA
@CottidaeSEA 2 ай бұрын
@@dreamsofcode Last time I had that issue, I solved it by forcibly fetching and caching with cron. A bit of a hacky and antipattern way of solving it, but it works really well.
@eveleynce
@eveleynce 2 ай бұрын
the number one question you should be asking yourself when setting up a data layer is "does it matter HOW my data is stored?" if you discover that it doesn't matter at all, a flat json file is a decent option. If you discover that you need to connect several devices together, then a fast but scalable network database like postrgres or ravendb will work JUST file. If you discover that you are needing to request the data far more frequently than your systems are able to handle, THEN you need a cache.
@hansenchrisw
@hansenchrisw 2 ай бұрын
+1, engineers often over complicate things. I think it was Dijkstra who said premature optimization is the root of all evil.
@its_maalik
@its_maalik Ай бұрын
Adding a cache should be the last resort to achieving good performance. Majority of applications will do just fine without a cache if they nail the data modeling and query optimizations.
@shady4tv
@shady4tv Ай бұрын
ironic that a video about redis comes out just before everyone drops it for going closed source.
@dreamsofcode
@dreamsofcode Ай бұрын
Bad timing! Although tbf, this can apply to any caching solution. + I get to review all of the forks that are coming
@shady4tv
@shady4tv Ай бұрын
@@dreamsofcode Honestly the timing is perfect! Redis is hot in the news cycle right now and you're right - this video isn't really about 'Redis' persay. But it's actually a great introduction to people who are uninformed about the software and want to get up to speed on all that is happening with it right now. I hope you get hella views from this bud! :)
@HUEHUEUHEPony
@HUEHUEUHEPony Ай бұрын
I mean it is only closed source if you are a big company
@mrmelon54
@mrmelon54 Ай бұрын
@@HUEHUEUHEPony no? The new licensing doesn't fall under the definition of open source, and isn't accepted by the open source initiative.
@Anshucodes
@Anshucodes 2 ай бұрын
Make a rust roadmap video Or make some tutorial 😂
@temie933
@temie933 Ай бұрын
Can you create a how to arch video? Showing how you configured arch Linux.
@lemonking4076
@lemonking4076 2 ай бұрын
Nice video! But I don't understand why would a dev torture themself with rust
@dreamsofcode
@dreamsofcode 2 ай бұрын
🤣🤣🤣😭😭😭
@lemonking4076
@lemonking4076 2 ай бұрын
@@dreamsofcodeit's just way too verbose and not easily readable 😂🙀 I hope this comment doesn't turn into a flamewar!!!
@evccyr
@evccyr 2 ай бұрын
I will do no push-ups for every like this comment gets. I'm sore from the last time.
@foziezzz1250
@foziezzz1250 2 ай бұрын
Would like to join you in this
@martin4ata933
@martin4ata933 Ай бұрын
LETS GOO
@sieunpark2160
@sieunpark2160 2 ай бұрын
first place!
@ariseyhun2085
@ariseyhun2085 2 ай бұрын
Ok
@itsme3217
@itsme3217 2 ай бұрын
Is this your life achievement ?
@pythagoran
@pythagoran 2 ай бұрын
Congratulations and/or I'm sorry to hear that
@sieunpark2160
@sieunpark2160 2 ай бұрын
@itsme3217 yeah my mom is proud of me 😁
@buddy.abc123
@buddy.abc123 2 ай бұрын
Rust syntax 😭😭😭🤢🤢🤢🤢
@dreamsofcode
@dreamsofcode 2 ай бұрын
I'm with ya. I think I'm gonna use Go more for demonstrating anything non language specific in the future!
@bavidlynx3409
@bavidlynx3409 2 ай бұрын
The comments and the video made me realise that caching is rather unnecessary and creates a lot of overhead and issues so imma stay away from it
@TheHTMLCode
@TheHTMLCode 2 ай бұрын
I don’t think that’s necessarily the best decision, if you don’t cache you will incur performance issues under certain circumstances. The example illustrated in this video is a very simple one which could have been solved by efficiently indexing your database, but as you scale or encounter more complex problems you may want to consider caching for latency sensitive functionality. At work we have a workflow that requires our operators to pick orders in a warehouse, fetching the pick list (all the instructions to carry out the picking of an order) takes around 500ms to generate. The pick list reflects the entire state of the current pick journey and uses a cache write through strategy to update the cached pick list after every scan in the warehouse. Without a cache, the front end would need to rebuild the list from the database every time it retrieved the next instruction, 500ms after completing a stop and fetching the next stop would suck, fetching from cache and having a result in 30ms is far better. The tradeoff here is maintaining the complexity of the cache in order to achieve the performance SLO (service level objective) we promised to our consumer (warehouse staff). For simple applications you may be able to keep away from caching but I’d definitely learn and keep it as a tool in your toolbox, I’m sure sometime in your career it’ll be useful :) hope that helps!
@Amejonah
@Amejonah 2 ай бұрын
I use caching (through postgres, I should really switch to redis) currently to make values live after restart of the application, as requesting the data takes a lot of time and consumes rate limit tokens.
@realbootybabe
@realbootybabe 2 ай бұрын
I like your videos so much! Thanks a lot 😄 How do you create your videos? What tools do you use? Maybe you want to create a video about that! 😎 thanks!
@dreamsofcode
@dreamsofcode 2 ай бұрын
Thank you! Yeah, I will be doing a video on my process this year I hope. I need to find the time to do so! Will drop a community post when I do :)
@site.x9448
@site.x9448 2 ай бұрын
@@dreamsofcodeawesome, thanks! Would be interesting to know as well!
I've been using Redis wrong this whole time...
20:53
Dreams of Code
Рет қаралды 324 М.
Using docker in unusual ways
12:58
Dreams of Code
Рет қаралды 379 М.
Monster dropped gummy bear 👻🤣 #shorts
00:45
Yoeslan
Рет қаралды 13 МЛН
когда одна дома // EVA mash
00:51
EVA mash
Рет қаралды 11 МЛН
Don’t take steroids ! 🙏🙏
00:16
Tibo InShape
Рет қаралды 33 МЛН
Зу-зу Күлпәш. Агроном. (5-бөлім)
55:20
ASTANATV Movie
Рет қаралды 615 М.
When RESTful architecture isn't enough...
21:02
Dreams of Code
Рет қаралды 238 М.
Understanding B-Trees: The Data Structure Behind Modern Databases
12:39
How principled coders outperform the competition
11:11
Coderized
Рет қаралды 1,5 МЛН
Signals. I spent 2 years to understand this part.
21:24
kimylamp
Рет қаралды 118 М.
new linux exploit is absolutely insane
8:29
Low Level Learning
Рет қаралды 408 М.
The purest coding style, where bugs are near impossible
10:25
Coderized
Рет қаралды 832 М.
98% Cloud Cost Saved By Writing Our Own Database
21:45
ThePrimeTime
Рет қаралды 239 М.
Testcontainers have forever changed the way I write tests
12:11
Dreams of Code
Рет қаралды 96 М.
The Algorithm Behind Spell Checkers
13:02
b001
Рет қаралды 360 М.
WHY IS THE HEAP SO SLOW?
17:53
Core Dumped
Рет қаралды 178 М.
Creepy Samsung Alarm cannot be turned off 😱🤣 #shorts
0:14
Adani Family
Рет қаралды 1,7 МЛН
Готовый миниПК от Intel (но от китайцев)
36:25
Ремонтяш
Рет қаралды 385 М.
Xiaomi Note 13 Pro по безумной цене в России
0:43
Простые Технологии
Рет қаралды 1,5 МЛН
Apple. 10 Интересных Фактов
24:26
Dameoz
Рет қаралды 69 М.
What’s your charging level??
0:14
Татьяна Дука
Рет қаралды 227 М.