-
Notifications
You must be signed in to change notification settings - Fork 291
Reduce unnecessary producerStateTable publish notifications #258
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
base: master
Are you sure you want to change the base?
Changes from all commits
c5eb157
43af582
c3341c3
6dfd3fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,23 +27,24 @@ ProducerStateTable::ProducerStateTable(RedisPipeline *pipeline, const string &ta | |
, m_tempViewActive(false) | ||
, m_pipe(pipeline) | ||
{ | ||
// num in luaSet and luaDel means number of elements that were added to the key set, | ||
// not including all the elements already present into the set. | ||
// publish notification is generated only when keyset was empty. | ||
string luaSet = | ||
"local added = redis.call('SADD', KEYS[2], ARGV[2])\n" | ||
"redis.call('SADD', KEYS[2], ARGV[2])\n" | ||
"for i = 0, #KEYS - 3 do\n" | ||
" redis.call('HSET', KEYS[3 + i], ARGV[3 + i * 2], ARGV[4 + i * 2])\n" | ||
"end\n" | ||
" if added > 0 then \n" | ||
"local num = redis.call('SCARD', KEYS[2])\n" | ||
" if num == 1 then \n" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, since we have only one notification at producer side for the keyset now, we might want to be cautious of the case where the notification could get dropped. In such case, the keyset will never be served to consumer even we may update keys/values in the keyset, as we will never generate notifications at producer again. Some mechanism might be needed here to prevent such cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unlikely redis will drop the notification, in that case probably a lot of bad things happened before the error. But I agree this is a valid concern, we should avoid single point of failure here. Currently I'm considering this extra check:
If it is not empty, likely the notification has been lost, generate new channel notification for each FV under the key so the pending data could be picked up. Due to race condition, there is very small possibility of false positive. We generate one extra notification, that is ok. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The mechanism looks ok to me. A few questions: 2, "Due to race condition" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FV here is the FV under _PRODUCESTATE_PUBLISH_REC:
each FV represents one keyset which has pending data. For race condition, consider such a scenario:
This will be really rare scenario, the extra notification is harmless other than causing orchagent to perform one more check. |
||
" redis.call('PUBLISH', KEYS[1], ARGV[1])\n" | ||
"end\n"; | ||
m_shaSet = m_pipe->loadRedisScript(luaSet); | ||
|
||
string luaDel = | ||
"local added = redis.call('SADD', KEYS[2], ARGV[2])\n" | ||
"redis.call('SADD', KEYS[2], ARGV[2])\n" | ||
"redis.call('SADD', KEYS[4], ARGV[2])\n" | ||
"redis.call('DEL', KEYS[3])\n" | ||
"if added > 0 then \n" | ||
"local num = redis.call('SCARD', KEYS[2])\n" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as before, to check the keyset number before we add the new key to be more precise. |
||
"if num == 1 then \n" | ||
" redis.call('PUBLISH', KEYS[1], ARGV[1])\n" | ||
"end\n"; | ||
m_shaDel = m_pipe->loadRedisScript(luaDel); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is probably better to move this check before we add the current key itself (before "redis.call('SADD', KEYS[2], ARGV[2])\n"), and we check whether "num == 0". With the code as is, in case the current key is the same as the exist key before, we could end up publishing more notifications than needed.