-
-
Notifications
You must be signed in to change notification settings - Fork 277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expired Locks remain in zset of digests [using "until_expired" lock] #653
Comments
Thank you for the wonderful report (and the praise of course) 😁 Thanks to your detailed explanation, I have an idea of what could go wrong. I believe the key doesn't have any entries but the key remains. I am not yet entirely sure but I believe it might be that when I remove an entry from a hash. set or list that the key's expiration is reset. I will do some digging on this. |
This may be a complete distraction, and I don't want to rush you for a response (any time is fine), but feeding back some more info from my own research in case it's helpful. It seems as though It seems that individual entries in a Redis Sorted Set (AKA zset) cannot have their own expiry or TTL. However, looking at the entries in On the bright side, from my perspective, this gives me a pretty clear mid-term solution for controlling memory usage - I can just schedule a job to run |
Weird, this is the opposite of what my tests say. I'll have to try and find a way to replicate this with a failing test. All my current tests don't leave locks behind. |
Important note, with more info tomorrow: I believe a substantial portion of my trouble has been caused by passing a namespace through sidekiq's redis config. This relies on redis-namespace, which does it's best to invisibly add and remove the namespace as appropriate for each command, but I suspect it can't possibly anticipate and adapt to all the possibilities of Lua scripts. I'm now removing this namespace, and will do some fresh testing tomorrow to try and figure out how much (if any!) of a problem still remains. This could potentially be a nice simple outcome, fixed with a little documentation warning against namespaces 🤞🏻 |
@francesmcmullin the redis namespace shouldn't be a problem as I have others using it. This is something else entirely but I am working on finding out exactly what. |
Thanks for that tip! Just a small update on my end, likely not news for you but just documenting my own understanding:
|
Good news! 🎉 I am quite confident I have discovered our problem. I believe that, once you have more orphan digests than your sidekiq-unique-jobs/lib/sidekiq_unique_jobs/orphans/ruby_reaper.rb Lines 57 to 64 in 94a203a
Confusingly, imo, ruby's
If it's helpful, I can try to write up a PR with a spec for this scenario. Of course, I may have misunderstood something about the internals or intentions with the reaper, in which case I'll happily follow your direction instead. |
You are right of course, I'll see if I can write a failing test for this scenario! |
Closes #653 The problem was that the reaper returns nil instead of the memo. Many thanks to @francesmcmullin for the wonderfully detailed report and investigation. Now we have a regression test for this behavior.
Closes #653 The problem was that the reaper returns nil instead of the memo. Many thanks to @francesmcmullin for the wonderfully detailed report and investigation. Now we have a regression test for this behavior.
* Fix edge case in ruby reaper Closes #653 The problem was that the reaper returns nil instead of the memo. Many thanks to @francesmcmullin for the wonderfully detailed report and investigation. Now we have a regression test for this behavior. * Mandatory rubocop commit
Released as v7.1.11 @francesmcmullin thank you so much for the help! |
Describe the bug
When locks are setup to expire using the TTL setting (both globally and at the job level), this should keep redis memory usage stable. However, while a lock's associated string keys are appropriately expired, the digest in the uniquejobs:digests zset is never cleaned up.
(This may be a duplicate of #637 , I've made a fresh issue because that thread seems to be focused on jobs which exit early with an error, whereas I've observed this issue in the absence of any errors)
[ It's entirely possible I've misunderstood some aspect of how this gem can or should work, any corrections to my assumptions or configuration are very welcome =) ]
Expected behavior
For locks/digests which have expired, I expect all data/trace to be cleaned up, leaving old locks with a memory footprint of 0
Current behavior
Strings under
uniquejobs:*
and hashes ofuniquejobs:*:LOCKED
anduniquejobs:*:UPGRADED
are all expired according to our configured TTL (24 hours), but the zsetuniquejobs:digests
continues to grow and includes digests many days old.Worker class
Sidekiq version: 6.2.2
Sidekiq Unique Jobs version: 7.1.8
Additional context
For our use case, most of our locks will be short lived. Our job arguments usually include an ID which is at risk of being handled multiple times briefly, but will never be used again after a few days. We get no value from holding digests longer, and it's an active drain on performance and risk to uptime if our redis memory usage increases forever.
I do not know if this is the sort of thing the reaper should be cleaning up, but as far as I can tell we do have the reaper enabled (default config):
Also thanks so much for a great gem and all the work on version 7 👏🏻 👏🏻 👏🏻
The text was updated successfully, but these errors were encountered: