Skip to content
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

DATAREDIS-976 - Integrate Cluster-Specific Lettuce PubSub Connection Code #450

Closed
wants to merge 4 commits into from

Conversation

brucecloud
Copy link

As part of scaling up our cloud infrastructure, we identified the need to migrate to clustered Redis for our services deployment that uses Spring Session. We are using

Spring Cloud Finchley.SR2
Spring Boot 2.0.5.RELEASE
Spring Session 2.1.4.RELEASE
Spring Data Redis 2.1.5.RELEASE
Lettuce 5.1.4.RELEASE

Testing with the Redis cluster showed that our designated service that processes events from Spring Session was not receiving any session expiration events. Looking closer, Redis keyspace event notification subscriptions required by Spring Session were not being registered on the Redis cluster master nodes. The subscriptions were present in the cluster slave nodes and were indicated in the info for the connections to the slaves, but were missing from the masters.

We looked into the Spring code and the Lettuce documentation and it appears that some of the code Lettuce uses to handle PubSub with clusters hasn't been integrated yet. The documentation in question is here https://github.com/lettuce-io/lettuce-core/wiki/Pub-Sub#redis-cluster.

We successfully integrated the Lettuce code into a branch of Spring Data Redis based on the 2.1.5.RELEASE and Spring Session began working as expected -- our service once again was receiving the session expiration events that are based on the Redis keyspace event notifications, and we can see the PubSub subscriptions on the Redis master nodes.

The Lettuce documentation specifies different code paths for user-space versus keyspace notifications from Redis. For our purposes we hard-coded the modifications to work as required by Spring Session (i.e., for keyspace notifications), but this fork has some additional code to expose the necessary flag to differentiate the two cases. A change will be required in Spring Session to utilize this new flag.

Caveats:
I haven't contributed before so I am looking for feedback/guidance.
This code has been tested as part of our branch based on the 2.1.5.RELEASE. For the fork, I have integrated it into 2.2.0-SNAPSHOT but we haven't tried this upgrade yet.
I am not sure how the unit tests for cluster code work, as I only have a standalone Redis installation in my local dev environment, so I have not attempted to add any unit tests for this functionality.

Thank you

…stener when connection factory is cluster-aware, including the flag to drive additional configuration Lettuce requires to support keyspace event notifications
@pivotal-issuemaster
Copy link

@brucecloud Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@pivotal-issuemaster
Copy link

@brucecloud Thank you for signing the Contributor License Agreement!

@mp911de mp911de changed the title Integrate Cluster-Specific Lettuce PubSub Connection Code DATAREDIS-976 - Integrate Cluster-Specific Lettuce PubSub Connection Code May 1, 2019
@mp911de
Copy link
Member

mp911de commented May 1, 2019

Hi @brucecloud, thanks for your first contribution. Check out our contribution guidelines that explain the ideal way of contributing to Spring Data projects. Typically, we create a Jira ticket first and then we discuss requirement and solution approaches. I filed DATAREDIS-976 to track this proposal.

We'll take a look in the next days.

@brucecloud
Copy link
Author

Thank you for the assistance, @mp911de.

@mp911de
Copy link
Member

mp911de commented May 3, 2019

As things stand now, we aren't able to integrate the changes into Moore M4 (Spring Data Redis 2.2 M4). This PR will slip to RC1.

@brucecloud
Copy link
Author

Thank you for the update

@mp911de
Copy link
Member

mp911de commented May 20, 2019

I reviewed this PR and this is probably the only way how to integrate Cluster Pub/Sub into Spring Data Redis.

Cluster Pub/Sub works similar to Standalone Pub/Sub except for Keyspace notifications. Keyspace events are not propagated across the entire cluster but remain node-local. This introduces a few challenges:

  1. To which nodes should we listen to (probably all master nodes that have slots assigned). For the simple approach, we can go with just all known master nodes
  2. How to adapt to cluster reconfiguration during runtime (i.e. without restarting the application): We don't have a solution for that yet.
  3. Referring to 1, where we PSUBSCRIBE to all master nodes to listen to keyspace events, we also get notified for non-keyspace events (i.e. all regular Pub/Sub messages). The actual problem is that due to listening to each individual node, we receive a single Pub/Sub message multiple times (e.g. 7 master nodes so we receive the same event 7 times because we have to subscribe to each individual node). Pub/Sub messages have no identity and with a cluster's distributed nature we have no reliable way to de-deduplicate messages.

The last point is actually something that worries me because this can easily lead to surprises in mixed setups (listening for keyspace notifications and consuming regular Pub/Sub messages). Beyond that, we also need an implementation for Reactive Pub/Sub.

/cc @vpavic @rwinch

I'm inclined to not include this change as the future of Cluster Pub/Sub is subject to change anyway: redis/redis#5766 (comment)

@rwinch
Copy link
Member

rwinch commented May 20, 2019

For what it is worth we are working on a Spring Session Redis variant that doesn't use events as we have had lots of people complain about the applications being overwhelmed with events.

@mp911de
Copy link
Member

mp911de commented May 21, 2019

Reiterating on that PR, we could probably integrate parts of this PR. The bit that causes trouble is enabling keyspace notification listening by subscribing to all masters and listening for events on all nodes.

Could you remove the keyspace listening part in preparation for the merge? We can investigate in a second step how you could hook into the subscription to customize it for keyspace listening.

@vpavic
Copy link
Contributor

vpavic commented Jun 3, 2019

Could you remove the keyspace listening part in preparation for the merge?

Hey @mp911de, not sure if I understood this part of your comment correctly, did you refer to Spring Session code when mentioning removal to keyspace listening part?

Thing is, with spring-projects/spring-session#1408 we're just adding an alternative Redis based implementation of SessionRepository. We cannot remove the parts related to the original RedisOperationsSessionRepository, as that would be a breaking change.

@mp911de
Copy link
Member

mp911de commented Jun 3, 2019

@vpavic my comment aimed for this PR and not towards Spring Session.

@brucecloud
Copy link
Author

@mp911de Thanks for the feedback; I apologize, I have been tied up with other work and haven't been able to revisit this.

I think my original attempt at what you have suggested was to only enable the keyspace notifications if an 'enableKeySpaceNotifications' flag was set to true when instantiating the LettuceClusterSubscription.

If you are suggesting that I should remove that part while the collective mind designs a better implementation for that option, I can certainly do that. Unfortunately it may be a while before I can get back to it though.

@rwinch Thanks for all you do with Spring Session, we have been using it for a couple years now. Re: creating a variant of Spring Session just to control/remove the event traffic -- that seems like overkill. If there were just a few more configuration options surfaced it would be easy enough to control which services receive the events, without having to extend RedisHttpSessionConfiguration. Just my two cents.

@mp911de
Copy link
Member

mp911de commented Jun 4, 2019

I apologize, I have been tied up with other work and haven't been able to revisit this.

All good. No worries. I can take your PR from here, I just didn't want to start without talking with you. The implementation would just enable Cluster Pub/Sub. Ideally, we can transform the code into a form where you are still able to hook into subscriptions (by providing a subclass or a customizer function) to listen to each individual node (with the mentioned drawbacks).

mp911de pushed a commit that referenced this pull request Jun 17, 2019
ClusterConnectionProvider now accepts cluster-specific connection interfaces for Pub/Sub connections.

Original pull request: #450.
mp911de added a commit that referenced this pull request Jun 17, 2019
mp911de added a commit that referenced this pull request Jun 17, 2019
…n classes.

LettuceConnection, LettuceClusterConnection, and LettuceSubscription can now be properly subclassed so they can be extended and created by LettuceConnectionFactory.

LettuceConnectionFactory provides template methods doCreateLettuceConnection and doCreateLettuceClusterConnection.

Original pull request: #450.
@mp911de
Copy link
Member

mp911de commented Jun 17, 2019

After going over the PR, almost nothing was left over. This was still a good exercise as we've identified gaps in tests and we made LettuceSubscription extensible. @brucecloud Can you have a look at LettuceClusterKeyspaceNotificationsTests to check whether these changes help you consuming keyspace notifications in Redis Cluster?

mp911de pushed a commit that referenced this pull request Jun 18, 2019
ClusterConnectionProvider now accepts cluster-specific connection interfaces for Pub/Sub connections.

Original pull request: #450.
mp911de added a commit that referenced this pull request Jun 18, 2019
mp911de added a commit that referenced this pull request Jun 18, 2019
…n classes.

LettuceConnection, LettuceClusterConnection, and LettuceSubscription can now be properly subclassed so they can be extended and created by LettuceConnectionFactory.

LettuceConnectionFactory provides template methods doCreateLettuceConnection and doCreateLettuceClusterConnection.

Original pull request: #450.
@mp911de
Copy link
Member

mp911de commented Jun 18, 2019

Superseded by #457.

@mp911de mp911de closed this Jun 18, 2019
christophstrobl pushed a commit that referenced this pull request Jul 3, 2019
ClusterConnectionProvider now accepts cluster-specific connection interfaces for Pub/Sub connections.

Original pull request: #450 & #457
christophstrobl pushed a commit that referenced this pull request Jul 3, 2019
christophstrobl pushed a commit that referenced this pull request Jul 3, 2019
…n classes.

LettuceConnection, LettuceClusterConnection, and LettuceSubscription can now be properly subclassed so they can be extended and created by LettuceConnectionFactory.

LettuceConnectionFactory provides template methods doCreateLettuceConnection and doCreateLettuceClusterConnection.

Original pull request: #450 & #457
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants