Skip to content

DATAREDIS-682 - Connect to Redis using unix domain sockets. #286

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

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ work/redis-%.conf:
echo notify-keyspace-events Ex >> $@
echo pidfile $(shell pwd)/work/redis-$*.pid >> $@
echo logfile $(shell pwd)/work/redis-$*.log >> $@
echo unixsocket $(shell pwd)/work/redis-$*.sock >> $@
echo unixsocketperm 755 >> $@
echo save \"\" >> $@
echo slaveof 127.0.0.1 6379 >> $@

Expand All @@ -42,6 +44,8 @@ work/redis-6379.conf:
echo notify-keyspace-events Ex >> $@
echo pidfile $(shell pwd)/work/redis-6379.pid >> $@
echo logfile $(shell pwd)/work/redis-6379.log >> $@
echo unixsocket $(shell pwd)/work/redis-6379.sock >> $@
echo unixsocketperm 755 >> $@
echo save \"\" >> $@

work/redis-%.pid: work/redis-%.conf work/redis/bin/redis-server
Expand Down Expand Up @@ -122,7 +126,7 @@ cluster-init: cluster-start cluster-meet cluster-slots
# Global
########
clean:
rm -rf work/*.conf work/*.log
rm -rf work/*.conf work/*.log dump.rdb

clobber:
rm -rf work
Expand Down
19 changes: 18 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.1.0.BUILD-SNAPSHOT</version>
<version>2.1.0.DATAREDIS-682-SNAPSHOT</version>

<name>Spring Data Redis</name>

Expand All @@ -24,6 +24,7 @@
<lettuce>5.0.0.RELEASE</lettuce>
<jedis>2.9.0</jedis>
<multithreadedtc>1.01</multithreadedtc>
<netty>4.1.15.Final</netty>
<java-module-name>spring.data.redis</java-module-name>
</properties>

Expand Down Expand Up @@ -85,6 +86,22 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<classifier>linux-x86_64</classifier>
<version>${netty}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-kqueue</artifactId>
<classifier>osx-x86_64</classifier>
<version>${netty}</version>
<scope>test</scope>
</dependency>

<!-- reactive -->
<dependency>
<groupId>io.projectreactor</groupId>
Expand Down
6 changes: 5 additions & 1 deletion src/main/asciidoc/new-features.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

New and noteworthy in the latest releases.

[[new-in-2.0.0]]
[[new-in-2.1.0]]
== New in Spring Data Redis 2.1

* Unix domain socket connections.

== New in Spring Data Redis 2.0

* Upgrade to Java 8.
Expand Down
86 changes: 50 additions & 36 deletions src/main/asciidoc/reference/redis.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -39,63 +39,77 @@ NOTE: Depending on the underlying configuration, the factory can return a new co

The easiest way to work with a `RedisConnectionFactory` is to configure the appropriate connector through the IoC container and inject it into the using class.

IMPORTANT: Unfortunately, currently, not all connectors support all Redis features. When invoking a method on the Connection API that is unsupported by the underlying library, an `UnsupportedOperationException` is thrown.
This situation is likely to be fixed in the future, as the various connectors mature.
IMPORTANT: Unfortunately, currently, not all connectors support all Redis features. When invoking a method on the Connection API that is unsupported by the underlying library, an `UnsupportedOperationException` is thrown.

[[redis:connectors:jedis]]
=== Configuring Jedis connector
[[redis:connectors:lettuce]]
=== Configuring Lettuce connector

http://github.com/xetorthio/jedis[Jedis] is one of the connectors supported by the Spring Data Redis module through the `org.springframework.data.redis.connection.jedis` package. In its simplest form, the Jedis configuration looks as follow:
https://github.com/lettuce-io/lettuce-core[Lettuce] is a http://netty.io/[netty]-based open-source connector supported by Spring Data Redis through the `org.springframework.data.redis.connection.lettuce` package.

[source,xml]
[source,java]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
@Configuration
class AppConfig {

<!-- Jedis ConnectionFactory -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"/>
@Bean
public LettuceConnectionFactory redisConnectionFactory() {

</beans>
return new LettuceConnectionFactory(new RedisStandaloneConfiguration("server", 6379));
}
}
----

For production use however, one might want to tweak the settings such as the host or password:
There are also a few Lettuce-specific connection parameters that can be tweaked. By default, all `LettuceConnection` s created by the `LettuceConnectionFactory` share the same thread-safe native connection for all non-blocking and non-transactional operations. Set `shareNativeConnection` to false to use a dedicated connection each time. `LettuceConnectionFactory` can also be configured with a `LettucePool` to use for pooling blocking and transactional connections, or all connections if `shareNativeConnection` is set to false.

[source,xml]
Lettuce integrates with netty's http://netty.io/wiki/native-transports.html[native transports] allowing to use unix domain sockets to communicate with Redis. Make sure to include the appropriate native transport dependencies that match your runtime environment.

[source,java]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
@Configuration
class AppConfig {

<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="server" p:port="6379" />
@Bean
public LettuceConnectionFactory redisConnectionFactory() {

</beans>
return new LettuceConnectionFactory(new RedisSocketConfiguration("/var/run/redis.sock"));
}
}
----

[[redis:connectors:lettuce]]
=== Configuring Lettuce connector
NOTE: Netty currently supports epoll (Linux) and kqueue (BSD/macOS) interfaces for OS-native transport.

https://github.com/mp911de/lettuce[Lettuce] is a http://netty.io/[netty]-based open-source connector supported by Spring Data Redis through the `org.springframework.data.redis.connection.lettuce` package.
[[redis:connectors:jedis]]
=== Configuring Jedis connector

Its configuration is probably easy to guess:
http://github.com/xetorthio/jedis[Jedis] is a community-driven connector supported by the Spring Data Redis module through the `org.springframework.data.redis.connection.jedis` package. In its simplest form, the Jedis configuration looks as follow:

[source,xml]
[source,java]
----
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
@Configuration
class AppConfig {

<bean id="lettuceConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory" p:host-name="server" p:port="6379"/>
@Bean
public JedisConnectionFactory redisConnectionFactory() {
return new JedisConnectionFactory();
}
}
----

</beans>
For production use however, one might want to tweak the settings such as the host or password:

[source,java]
----
@Configuration
class RedisConfiguration {

There are also a few Lettuce-specific connection parameters that can be tweaked. By default, all `LettuceConnection` s created by the `LettuceConnectionFactory` share the same thread-safe native connection for all non-blocking and non-transactional operations. Set `shareNativeConnection` to false to use a dedicated connection each time. `LettuceConnectionFactory` can also be configured with a `LettucePool` to use for pooling blocking and transactional connections, or all connections if `shareNativeConnection` is set to false.
@Bean
public JedisConnectionFactory redisConnectionFactory() {

RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("server", 6379);
return new JedisConnectionFactory(config);
}
}
----

[[redis:sentinel]]
== Redis Sentinel Support
Expand All @@ -105,7 +119,7 @@ For dealing with high available Redis there is support for http://redis.io/topic
[source,java]
----
/**
* jedis
* Jedis
*/
@Bean
public RedisConnectionFactory jedisConnectionFactory() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.connection;

/**
* Interface to be implemented by any object that exposes a database index or wishes to be updated with a database
* index.
*
* @author Mark Paluch
* @since 2.1
*/
public interface DatabaseAware {

/**
* @return the Redis database index.
*/
int getDatabase();

/**
* Sets the index of the database used by this connection factory. Default is 0.
*
* @param index database index.
*/
void setDatabase(int index);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@
* @author Mark Paluch
* @since 1.7
*/
public class RedisClusterConfiguration {
public class RedisClusterConfiguration implements RedisPasswordAware {

private static final String REDIS_CLUSTER_NODES_CONFIG_PROPERTY = "spring.redis.cluster.nodes";
private static final String REDIS_CLUSTER_MAX_REDIRECTS_CONFIG_PROPERTY = "spring.redis.cluster.max-redirects";

private Set<RedisNode> clusterNodes;
private final Set<RedisNode> clusterNodes;
private @Nullable Integer maxRedirects;
private RedisPassword password = RedisPassword.none();

Expand Down Expand Up @@ -181,20 +181,20 @@ private void appendClusterNodes(Set<String> hostAndPorts) {
}
}

/**
* Get the {@link RedisPassword} defined.
*
* @return never {@literal null}.
* @since 2.0
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisPasswordAware#getPassword()
*/
@Override
public RedisPassword getPassword() {
return password;
}

/**
* @param password must not be {@literal null}.
* @since 2.0
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisPasswordAware#setPassword(org.springframework.data.redis.connection.RedisPassword)
*/
@Override
public void setPassword(RedisPassword password) {

Assert.notNull(password, "RedisPassword must not be null!");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.connection;

/**
* Interface to be implemented by any object that exposes a {@link RedisPassword} configuration or wishes to be updated
* with a password.
*
* @author Mark Paluch
* @since 2.1
*/
public interface RedisPasswordAware {

/**
* @return the Redis password.
*/
RedisPassword getPassword();

/**
* Sets the Redis password. Defaults to {@link RedisPassword#none()}.
*
* @param password the password to set, must not be {@literal null}.
*/
void setPassword(RedisPassword password);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@
* @author Mark Paluch
* @since 1.4
*/
public class RedisSentinelConfiguration {
public class RedisSentinelConfiguration implements RedisPasswordAware, DatabaseAware {

private static final String REDIS_SENTINEL_MASTER_CONFIG_PROPERTY = "spring.redis.sentinel.master";
private static final String REDIS_SENTINEL_NODES_CONFIG_PROPERTY = "spring.redis.sentinel.nodes";

private @Nullable NamedNode master;
private Set<RedisNode> sentinels;
private final Set<RedisNode> sentinels;
private int database;
private RedisPassword password = RedisPassword.none();

Expand Down Expand Up @@ -217,39 +217,41 @@ private void appendSentinels(Set<String> hostAndPorts) {
}
}

/**
* @return the initial db index.
* @since 2.0
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.DatabaseAware#getDatabase()
*/
@Override
public int getDatabase() {
return database;
}

/**
* Sets the index of the database used by this connection factory. Default is 0.
*
* @param index database index.
* @since 2.0
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.DatabaseAware#setDatabase(int)
*/
@Override
public void setDatabase(int index) {

Assert.isTrue(index >= 0, () -> String.format("Invalid DB index '%s' (a positive index required)", index));

this.database = index;
}

/**
* @return never {@literal null}.
* @since 2.0
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisPasswordAware#getPassword()
*/
@Override
public RedisPassword getPassword() {
return password;
}

/**
* @param password must not be {@literal null}.
* @since 2.0
/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisPasswordAware#setPassword(org.springframework.data.redis.connection.RedisPassword)
*/
@Override
public void setPassword(RedisPassword password) {

Assert.notNull(password, "RedisPassword must not be null!");
Expand Down
Loading