Поскольку решения NoSQL становятся все более популярными для решения многих видов проблем, современные проекты чаще используют некоторые (или несколько) NoSQL вместо (или бок о бок) традиционных СУБД. Я уже рассказал о своем опыте работы с MongoDB в этом , этом и этом постах. В этом посте я хотел бы немного переключиться на Redis , продвинутый магазин значений ключей.
Помимо очень богатой семантики ключ-значение, Redis также поддерживает обмен сообщениями и транзакции из публикации. В этой статье я просто коснусь поверхности и продемонстрирую, как просто интегрировать Redis в приложение Spring. Как всегда, мы начнем с файла POM Maven для нашего проекта:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
< project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelversion >4.0.0</ modelversion > < groupid >com.example.spring</ groupid > < artifactid >redis</ artifactid > < version >0.0.1-SNAPSHOT</ version > < packaging >jar</ packaging > < properties > < project.build.sourceencoding >UTF-8</ project.build.sourceencoding > < spring.version >3.1.0.RELEASE</ spring.version > </ properties > < dependencies > < dependency > < groupid >org.springframework.data</ groupid > < artifactid >spring-data-redis</ artifactid > < version >1.0.0.RELEASE</ version > </ dependency > < dependency > < groupid >cglib</ groupid > < artifactid >cglib-nodep</ artifactid > < version >2.2</ version > </ dependency > < dependency > < groupid >log4j</ groupid > < artifactid >log4j</ artifactid > < version >1.2.16</ version > </ dependency > < dependency > < groupid >redis.clients</ groupid > < artifactid >jedis</ artifactid > < version >2.0.0</ version > < type >jar</ type > </ dependency > < dependency > < groupid >org.springframework</ groupid > < artifactid >spring-core</ artifactid > < version >${spring.version}</ version > </ dependency > < dependency > < groupid >org.springframework</ groupid > < artifactid >spring-context</ artifactid > < version >${spring.version}</ version > </ dependency > </ dependencies > </ project > |
Spring Data Redis — это еще один проект под зонтиком Spring Data, который обеспечивает плавное внедрение Redis в ваше приложение. Существует несколько клиентов Redis для Java, и я выбрал Jedis, поскольку он стабилен и рекомендован командой Redis на момент написания этого поста.
Мы начнем с простой настройки и сначала представим необходимые компоненты. Затем, по мере продвижения вперед, конфигурация будет немного расширена, чтобы продемонстрировать возможности pub-sub. Благодаря поддержке конфигурации Java, мы создадим класс конфигурации и будем строго типизировать все наши зависимости, больше не будет XML:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package com.example.redis.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericToStringSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class AppConfig { @Bean JedisConnectionFactory jedisConnectionFactory() { return new JedisConnectionFactory(); } @Bean RedisTemplate< String, Object > redisTemplate() { final RedisTemplate< String, Object > template = new RedisTemplate< String, Object >(); template.setConnectionFactory( jedisConnectionFactory() ); template.setKeySerializer( new StringRedisSerializer() ); template.setHashValueSerializer( new GenericToStringSerializer< Object >( Object. class ) ); template.setValueSerializer( new GenericToStringSerializer< Object >( Object. class ) ); return template; } } |
Это в основном все, что нам нужно, предполагая, что у нас есть один сервер Redis , работающий на локальном хосте с конфигурацией по умолчанию. Давайте рассмотрим несколько распространенных вариантов использования: установка ключа для некоторого значения, сохранение объекта и, наконец, реализация pub-sub. Хранить и извлекать пару ключ / значение очень просто:
1
2
3
4
5
6
7
8
9
|
@Autowired private RedisTemplate< String, Object > template; public Object getValue( final String key ) { return template.opsForValue().get( key ); } public void setValue( final String key, final String value ) { template.opsForValue().set( key, value ); } |
При желании ключ может быть установлен на срок действия (еще одна полезная функция Redis ), например, срок действия ключей истекает через 1 секунду:
1
2
3
4
|
public void setValue( final String key, final String value ) { template.opsForValue().set( key, value ); template.expire( key, 1 , TimeUnit.SECONDS ); } |
Произвольные объекты могут быть сохранены в Redis в виде хэшей (карт), например, можно сохранить экземпляр некоторого класса User
1
2
3
4
5
6
7
|
public class User { private final Long id; private String name; private String email; // Setters and getters are omitted for simplicity } |
в Redis, используя комбинацию клавиш «user: <id>» :
01
02
03
04
05
06
07
08
09
10
|
public void setUser( final User user ) { final String key = String.format( "user:%s" , user.getId() ); final Map< String, Object > properties = new HashMap< String, Object >(); properties.put( "id" , user.getId() ); properties.put( "name" , user.getName() ); properties.put( "email" , user.getEmail() ); template.opsForHash().putAll( key, properties); } |
Соответственно, объект может быть легко проверен и извлечен с использованием идентификатора .
1
2
3
4
5
6
7
8
|
public User getUser( final Long id ) { final String key = String.format( "user:%s" , id ); final String name = ( String )template.opsForHash().get( key, "name" ); final String email = ( String )template.opsForHash().get( key, "email" ); return new User( id, name, email ); } |
Есть много, намного больше, что можно сделать с помощью Redis , я настоятельно рекомендую взглянуть на это. Это, конечно, не серебряная пуля, но она может легко решить многие сложные проблемы. Наконец, позвольте мне показать, как использовать обмен сообщениями в пабе с Redis . Давайте добавим немного больше конфигурации здесь (как часть класса AppConfig):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@Bean MessageListenerAdapter messageListener() { return new MessageListenerAdapter( new RedisMessageListener() ); } @Bean RedisMessageListenerContainer redisContainer() { final RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory( jedisConnectionFactory() ); container.addMessageListener( messageListener(), new ChannelTopic( "my-queue" ) ); return container; } |
Стиль определения прослушивателя сообщений должен выглядеть очень знакомым для пользователей Spring: как правило, мы используем тот же подход для определения прослушивателей сообщений JMS. Пропущенный фрагмент — это наше определение класса RedisMessageListener:
01
02
03
04
05
06
07
08
09
10
11
|
package com.example.redis.impl; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; public class RedisMessageListener implements MessageListener { @Override public void onMessage(Message message, byte [] paramArrayOfByte) { System.out.println( "Received by RedisMessageListener: " + message.toString() ); } } |
Теперь, когда у нас есть прослушиватель сообщений, давайте посмотрим, как мы можем поместить некоторые сообщения в очередь, используя Redis . Как всегда, все довольно просто:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
@Autowired private RedisTemplate< String, Object > template; public void publish( final String message ) { template.execute( new RedisCallback< Long >() { @SuppressWarnings ( "unchecked" ) @Override public Long doInRedis( RedisConnection connection ) throws DataAccessException { return connection.publish( ( ( RedisSerializer< String > )template.getKeySerializer() ).serialize( "queue" ), ( ( RedisSerializer< Object > )template.getValueSerializer() ).serialize( message ) ); } } ); } |
Это в основном все для очень быстрого знакомства, но этого достаточно, чтобы влюбиться в Redis .
Ссылка: Использование Redis с Spring от нашего партнера по JCG Андрея Редько в блоге Андрея Редько {devmind} .