spring+redis 集群下的操作

文章就是记录一下工作当中的用到的点,与测试方法以备用,会不断更新。

配置文件spring-redis.xml:

<?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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">


<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/redis.properties</value>
</list>
</property>
</bean>
<!-- xml方式配置cluster-->
<bean id= "clusterRedisNodes1" class="org.springframework.data.redis.connection.RedisNode" >
<constructor-arg value="${redis.host1}" />
<constructor-arg value="${redis.port1}" type="int" />
</bean>
<bean id= "clusterRedisNodes2" class="org.springframework.data.redis.connection.RedisNode" >
<constructor-arg value="${redis.host2}" />
<constructor-arg value="${redis.port2}" type="int" />
</bean>
<bean id= "clusterRedisNodes3" class="org.springframework.data.redis.connection.RedisNode" >
<constructor-arg value="${redis.host3}" />
<constructor-arg value="${redis.port3}" type="int" />
</bean>
<bean id= "clusterRedisNodes4" class="org.springframework.data.redis.connection.RedisNode" >
<constructor-arg value="${redis.host4}" />
<constructor-arg value="${redis.port4}" type="int" />
</bean>
<bean id= "clusterRedisNodes5" class="org.springframework.data.redis.connection.RedisNode" >
<constructor-arg value="${redis.host5}" />
<constructor-arg value="${redis.port5}" type="int" />
</bean>
<bean id= "clusterRedisNodes6" class="org.springframework.data.redis.connection.RedisNode" >
<constructor-arg value="${redis.host6}" />
<constructor-arg value="${redis.port6}" type="int" />
</bean>

<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration" >
<property name="maxRedirects" value="${spring.redis.cluster.max-redirects}" >
</property>
<property name="clusterNodes" >
<set>
<ref bean="clusterRedisNodes1" />
<ref bean="clusterRedisNodes2" />
<ref bean="clusterRedisNodes3" />
<ref bean="clusterRedisNodes4" />
<ref bean="clusterRedisNodes5" />
<ref bean="clusterRedisNodes6" />
</set>
</property>
</bean>
<bean id= "poolConfig" class ="redis.clients.jedis.JedisPoolConfig">
<property name="minIdle" value="${redis.minIdle}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean >
<!-- 集群 -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:usePool="true">
<constructor-arg index="0" ref="redisClusterConfiguration" />
<constructor-arg index="1" ref="poolConfig"></constructor-arg>
</bean >
<!-- 单机 -->
<!--<bean id="jedisConnectionFactory"-->
<!--class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"-->
<!--p:hostName="192.168.1.42" p:port="6379" p:password="gxdgroup" p:database="0"-->
<!--p:poolConfig-ref="poolConfig" p:usePool="true"/>-->
<!-- Spring Data Redis 设置 -->
<!-- redis 序列化策略 ,通常情况下key值采用String序列化策略, -->
<!-- 如果不指定序列化策略,StringRedisTemplate的key和value都将采用String序列化策略; -->
<bean id="jsonRedisSerializer" class="com.xdth.redis.JsonUtil.JsonRedisSeriaziler"/>

<!--<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">-->
<!--&lt;!&ndash;如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!! &ndash;&gt;-->
<!--<property name="connectionFactory" ref="jedisConnectionFactory" />-->
<!--<property name="keySerializer" >-->
<!--<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />-->
<!--</property>-->
<!--<property name="hashKeySerializer">-->
<!--<bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>-->
<!--</property>-->
<!--</bean>-->

<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- 自动扫描dao和service包(自动注入) -->
<context:component-scan base-package="com.xdth.redis.*" >
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service" />
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />
</context:component-scan>
</beans>

 


属性文件redis.properties:自己redis的ip与端口

redis.host1=127.0.0.1
redis.port1=7001

redis.host2=127.0.0.1
redis.port2=7002

redis.host3=127.0.0.1
redis.port3=7003

redis.host4=127.0.0.1
redis.port4=7004

redis.host5=127.0.0.1
redis.port5=7005

redis.host6=127.0.0.1
redis.port6=7006

redis.minIdle=1
redis.maxIdle=300
redis.maxActive=600
redis.maxWait=10000
redis.testOnBorrow=true
spring.redis.cluster.max-redirects= 3

StringRedisTemplate (key与value的默认序列化是stringSerializer)继承自 RedisTemplate (JdkSerializationRedisSerializer默认的序列化机制)

操作具体

redis的string类型操作

 
  public static void testString(){
ApplicationContext ac = new ClassPathXmlApplicationContext("spring-redis.xml");
StringRedisTemplate template = (StringRedisTemplate) ac.getBean("stringRedisTemplate");
ValueOperations<String, String> stringOpe = template.opsForValue();
//插入 第三个参数为指定过期时间
stringOpe.set("mingren","01");
stringOpe.set("zuozhu","02",1);
stringOpe.set("xiaoying","03",1, TimeUnit.MINUTES);
//重新设置值追加
stringOpe.append("mingren","hero");
//获取值
String mingren01 = stringOpe.get("mingren");
System.out.println("mingren :"+mingren01);
//获取原来的值 并设置为新的值
String mingrenGetAndSet = stringOpe.getAndSet("mingren", "01heros");
System.out.println("mingrenGetAndSet :"+mingrenGetAndSet);
String mingren02 = stringOpe.get("mingren");
System.out.println("mingren :"+mingren02);
//截取value值得一部分 0- -1 位全部
String mingrenLL = stringOpe.get("mingren", 0, -1);
System.out.println("mingrenLL :"+mingrenLL);
//bit的使用 bit 的位图 第5位设置为1 其他的位置为0
Boolean bit = stringOpe.setBit("bit", 5, true);
System.out.println("bit :"+bit);
Boolean bit1 = stringOpe.getBit("bit", 5);
// BitSet java.util包下 位可以用来统计用户访问量 统计有多少位为1
BitSet bitSet= BitSet.valueOf(stringOpe.get("bit").getBytes());
System.out.println(" bitSet.cardinality() :"+bitSet.cardinality());

System.out.println("插入完成");

}

redis实现队列

队列实现

@Component("redisMQ")
public class RedisMQ implements IRedisMQ {
@Resource
private StringRedisTemplate stringRedisTemplate;

@Resource
private JsonRedisSeriaziler jsonRedisSerializer;

/**
* 压栈
*
* @param key
* @param value
* @return
*/
public Long push(String key, String value) {
return stringRedisTemplate.opsForList().leftPush(key, value);
}

/**
* 出栈
*
* @param key
* @return
*/
public String pop(String key) {
return stringRedisTemplate.opsForList().leftPop(key);
}

/**
* 入队
*
* @param key
* @param value
* @return
*/
public Long in(String key, String value) {
return stringRedisTemplate.opsForList().rightPush(key, value);
}

/**
* 从队列的头,插入对象
*/
public <T> Long pushFromHead(String key,T value){
return stringRedisTemplate.opsForList().leftPush(key, this.jsonRedisSerializer.seriazileAsString(value));
}

/**
* 从对尾,插入对象
* @param value
*/
public <T> Long pushFromTail(String key,T value){
return stringRedisTemplate.opsForList().rightPush(key, this.jsonRedisSerializer.seriazileAsString(value));
}

/**
* 出队
*
* @param key
* @return
*/
public String out(String key) {
return stringRedisTemplate.opsForList().leftPop(key);
}

public String out(String key,int timeout){
return stringRedisTemplate.opsForList().leftPop(key, timeout, TimeUnit.SECONDS);
}

/**
* 出队,从对头出队
* noblocking
* @return null if no item in queue
*/
public <T> T removeFromHead(String key,Class<T> clazz) {
return this.jsonRedisSerializer.deserializeAsObject(stringRedisTemplate.opsForList().leftPop(key).toString(),clazz);
}
/**
* 出队,从对头出队
* noblocking
* @return null if no item in queue
*/
public <T> T removeFromHead(String key, int timeout,Class<T> clazz) {
return this.jsonRedisSerializer.deserializeAsObject(stringRedisTemplate.opsForList().leftPop(key, timeout, TimeUnit.SECONDS).toString(),clazz) ;
}

/**
* 出队,从队尾出队
* noblocking
* @return null if no item in queue
*/
public <T> T removeFromTail(String key,Class<T> clazz){
return this.jsonRedisSerializer.deserializeAsObject(stringRedisTemplate.opsForList().rightPop(key).toString(),clazz);
}
/**
* 栈/队列长
*
* @param key
* @return
*/
public Long length(String key) {
return stringRedisTemplate.opsForList().size(key);
}

/**
* 范围检索
*
* @param key
* @param start
* @param end
* @return
*/
public List<String> range(String key, int start, int end) {
return stringRedisTemplate.opsForList().range(key, start, end);
}

/**
* 移除
*
* @param key
* @param i
* @param value
*/
public void remove(String key, long i, String value) {
stringRedisTemplate.opsForList().remove(key, i, value);
}

/**
* 检索
*
* @param key
* @param index
* @return
*/
public String index(String key, long index) {
return (String) stringRedisTemplate.opsForList().index(key, index);
}

/**
* 置值
*
* @param key
* @param index
* @param value
*/
public void set(String key, long index, String value) {
stringRedisTemplate.opsForList().set(key, index, value);
}

/**
* 裁剪
*
* @param key
* @param start
* @param end
*/
public void trim(String key, long start, int end) {
stringRedisTemplate.opsForList().trim(key, start, end);
}

}



转载于:https://www.cnblogs.com/feixian/p/6257233.html

在使用 Spring 框架结合 WebSocket 和 Redis 集群实现消息推送功能时,核心思路是通过 WebSocket 建立客户端与服务器之间的双向通信,并利用 Redis 集群实现消息的发布与订阅机制,从而支持分布式环境下的实时消息推送。 ### 架构设计 整个系统可以分为以下几个主要组件: - **WebSocket 服务端**:负责与客户端建立连接,并处理消息的接收与发送。 - **Redis Pub/Sub**:用于在多个服务节点之间同步消息,确保消息能够被正确地广播或定向推送。 - **Spring Boot 应用**:整合 WebSocket 和 Redis,提供统一的消息处理逻辑。 ### 实现步骤 #### 1. 配置 WebSocket 在 Spring Boot 中启用 WebSocket 支持,可以通过配置类实现 `WebSocketMessageBrokerConfigurer` 接口[^1]。示例代码如下: ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.setApplicationDestinationPrefixes("/app"); registry.enableSimpleBroker("/topic", "/queue"); } } ``` #### 2. 配置 Redis 集群 在 `application.yml` 中配置 Redis 集群地址: ```yaml spring: redis: cluster: nodes: - 192.168.1.101:6379 - 192.168.1.102:6379 - 192.168.1.103:6379 - 192.168.1.104:6379 - 192.168.1.105:6379 - 192.168.1.106:6379 ``` #### 3. 配置 Redis 消息监听 使用 `RedisMessageListenerContainer` 来监听特定频道的消息,并将其转发给 WebSocket 客户端: ```java @Component public class RedisSubscriber { private final SimpMessagingTemplate messagingTemplate; public RedisSubscriber(SimpMessagingTemplate messagingTemplate) { this.messagingTemplate = messagingTemplate; } public void onMessage(Message message, byte[] pattern) { String channel = new String(message.getChannel()); String body = new String(message.getBody()); // 将消息转发给 WebSocket 客户端 messagingTemplate.convertAndSend("/topic/messages", body); } } ``` 在配置类中注册 Redis 消息监听器: ```java @Configuration public class RedisConfig { @Bean public RedisMessageListenerContainer redisContainer(RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(connectionFactory); container.addMessageListener(listenerAdapter, new PatternTopic("/topic/messages")); return container; } @Bean public MessageListenerAdapter listenerAdapter(RedisSubscriber subscriber) { return new MessageListenerAdapter(subscriber, "onMessage"); } } ``` #### 4. 发送消息到 Redis 在业务逻辑中,可以通过 `RedisTemplate` 将消息发布到 Redis 的指定频道: ```java @Service public class MessageService { private final RedisTemplate<String, String> redisTemplate; public MessageService(RedisTemplate<String, String> redisTemplate) { this.redisTemplate = redisTemplate; } public void sendMessage(String message) { redisTemplate.convertAndSend("/topic/messages", message); } } ``` #### 5. 客户端连接与接收消息 前端可以使用 SockJS 和 STOMP.js 连接到 WebSocket 服务并订阅消息: ```html <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/lib/stomp.min.js"></script> <script> const socket = new SockJS('/ws'); const stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/messages', function (message) { console.log('Received: ' + message.body); }); }); // 发送消息 function sendMessage() { stompClient.send("/app/sendMessage", {}, JSON.stringify({'name': 'Test'})); } </script> ``` ### 总结 通过上述配置,Spring WebSocket 可以与 Redis 集群结合,实现跨服务节点的实时消息推送。WebSocket 提供了实时通信的能力,而 Redis Pub/Sub 则确保了消息能够在分布式环境中正确广播。这种架构适用于需要高并发、低延迟的消息推送场景。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值