什么行业最需要做网站建设软件大全网址
- 作者: 五速梦信息网
- 时间: 2026年04月20日 09:17
当前位置: 首页 > news >正文
什么行业最需要做网站建设,软件大全网址,微信里面的小程序,营销成功的案例为了减轻项目的中间件臃肿#xff0c;由于我们项目本身就应用了 Redis#xff0c;正好 Redis 的也具备订阅发布监听的特性#xff0c;正好应对 Etcd 的功能#xff0c;所以本次给大家讲解如何使用 Redis 消息订阅发布来替代 Etcd 的解决方案。接下来#xff0c;我们先看 R… 为了减轻项目的中间件臃肿由于我们项目本身就应用了 Redis正好 Redis 的也具备订阅发布监听的特性正好应对 Etcd 的功能所以本次给大家讲解如何使用 Redis 消息订阅发布来替代 Etcd 的解决方案。接下来我们先看 Redis 订阅发布的常见情景…… Redis 订阅发布公共类
RedisConfig.java
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.net.UnknownHostException;Configuration
ComponentScan({cn.hutool.extra.spring})
public class RedisConfig {BeanRedisMessageListenerContainer container (RedisConnectionFactory redisConnectionFactory){RedisMessageListenerContainer container new RedisMessageListenerContainer();container.setConnectionFactory(redisConnectionFactory);return container;}Beanpublic RedisTemplateString, Object redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {RedisTemplateString, Object template new RedisTemplate();// 连接工厂template.setConnectionFactory(redisConnectionFactory);// 序列化配置Jackson2JsonRedisSerializer objectJackson2JsonRedisSerializer new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);StringRedisSerializer stringRedisSerializer new StringRedisSerializer();// 配置具体序列化// key采用string的序列化方式template.setKeySerializer(stringRedisSerializer);// hash的key采用string的序列化方式template.setHashKeySerializer(stringRedisSerializer);// value序列化采用jacksontemplate.setValueSerializer(objectJackson2JsonRedisSerializer);// hash的value序列化采用jacksontemplate.setHashValueSerializer(objectJackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}
}
RedisUtil.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;Slf4j
Component
public class RedisUtil {Resourceprivate RedisTemplate redisTemplate;/*** 消息发送* param topic 主题* param message 消息/public void publish(String topic, String message) {redisTemplate.convertAndSend(topic, message);}
}
application.yml
server:port: 7077
spring:application:name: redis-demoredis:host: localhosttimeout: 3000jedis:pool:max-active: 300max-idle: 100max-wait: 10000port: 6379
RedisController.java
import org.springframework.web.bind.annotation.;
import javax.annotation.Resource;/*** author Lux Sun* date 2023/9/12/
RestController
RequestMapping(/redis)
public class RedisController {Resourceprivate RedisUtil redisUtil;PostMappingpublic String publish(RequestParam String topic, RequestParam String msg) {redisUtil.publish(topic, msg);return 发送成功: topic - msg;}
} 一、业务情景1 个消费者监听 1 个 Topic
教程三步走下文业务情景类似不再描述
实现接口 MessageListener消息订阅绑定业务 Topic重写 onMessage 消费者业务方法
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;Slf4j
Component
public class RedisReceiver1 implements MessageListener {Resourceprivate RedisMessageListenerContainer container;/** 重点关注这方法, 进行消息订阅/PostConstructpublic void init() {MessageListenerAdapter adapter new MessageListenerAdapter(this);// 绑定 Topic 语法为正则表达式container.addMessageListener(adapter, new PatternTopic(topic1.));}Overridepublic void onMessage(Message message, byte[] bytes) {String key new String(message.getChannel());String value new String(message.getBody());log.info(Key: {}, key);log.info(Value: {}, value);}
}
测试
curl –location 127.0.0.1:7077/redis
–header Content-Type: application/x-www-form-urlencoded
–data-urlencode topictopic1.msg
–data-urlencode msg我是消息1
结果
2023-11-15 10:22:38.445 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Key: topic1.msg
2023-11-15 10:22:38.445 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Value: 我是消息1 二、业务情景1 个消费者监听 N 个 Topic
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;Slf4j
Component
public class RedisReceiver1 implements MessageListener {Resourceprivate RedisMessageListenerContainer container;/*** 重点关注这方法, 进行消息订阅/PostConstructpublic void init() {MessageListenerAdapter adapter new MessageListenerAdapter(this);// 绑定 Topic 语法为正则表达式container.addMessageListener(adapter, new PatternTopic(topic1.));// 只需再绑定业务 Topic 即可container.addMessageListener(adapter, new PatternTopic(topic2.));}Overridepublic void onMessage(Message message, byte[] bytes) {String key new String(message.getChannel());String value new String(message.getBody());log.info(Key: {}, key);log.info(Value: {}, value);}
}
测试
curl –location 127.0.0.1:7077/redis
–header Content-Type: application/x-www-form-urlencoded
–data-urlencode topictopic2.msg
–data-urlencode msg我是消息2
结果
2023-11-15 10:22:38.445 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Key: topic2.msg
2023-11-15 10:22:38.445 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Value: 我是消息2 三、业务情景N 个消费者监听 1 个 Topic
我们看一下现在又新增一个 RedisReceiver2按理讲测试的时候RedisReceiver1 和 RedisReceiver2 会同时收到消息
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;Slf4j
Component
public class RedisReceiver2 implements MessageListener {Resourceprivate RedisMessageListenerContainer container;/** 重点关注这方法, 进行消息订阅/PostConstructpublic void init() {MessageListenerAdapter adapter new MessageListenerAdapter(this);// 绑定 Topic 语法为正则表达式container.addMessageListener(adapter, new PatternTopic(topic1.));}Overridepublic void onMessage(Message message, byte[] bytes) {String key new String(message.getChannel());String value new String(message.getBody());log.info(Key: {}, key);log.info(Value: {}, value);}
}
测试
curl –location 127.0.0.1:7077/redis
–header Content-Type: application/x-www-form-urlencoded
–data-urlencode topictopic1.msg
–data-urlencode msg我是消息1
结果
2023-11-15 10:22:38.445 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Key: topic1.msg
2023-11-15 10:22:38.449 INFO 59189 — [ container-3] com.xxx.redis.demo.RedisReceiver2 : Key: topic1.msg
2023-11-15 10:22:38.545 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Value: 我是消息1
2023-11-15 10:22:38.645 INFO 59189 — [ container-3] com.xxx.redis.demo.RedisReceiver2 : Value: 我是消息1 四、业务情景N 个消费者监听 N 个 Topic
都到这阶段了应该不难理解了吧~
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;Slf4j
Component
public class RedisReceiver2 implements MessageListener {Resourceprivate RedisMessageListenerContainer container;/*** 重点关注这方法, 进行消息订阅/PostConstructpublic void init() {MessageListenerAdapter adapter new MessageListenerAdapter(this);// 绑定 Topic 语法为正则表达式container.addMessageListener(adapter, new PatternTopic(topic1.));// 只需再绑定业务 Topic 即可container.addMessageListener(adapter, new PatternTopic(topic2.));}Overridepublic void onMessage(Message message, byte[] bytes) {String key new String(message.getChannel());String value new String(message.getBody());log.info(Key: {}, key);log.info(Value: {}, value);}
}
测试
curl –location 127.0.0.1:7077/redis
–header Content-Type: application/x-www-form-urlencoded
–data-urlencode topictopic2.msg
–data-urlencode msg我是消息2
结果
2023-11-15 10:22:38.445 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Key: topic2.msg
2023-11-15 10:22:38.449 INFO 59189 — [ container-3] com.xxx.redis.demo.RedisReceiver2 : Key: topic2.msg
2023-11-15 10:22:38.545 INFO 59189 — [ container-2] com.xxx.redis.demo.RedisReceiver1 : Value: 我是消息2
2023-11-15 10:22:38.645 INFO 59189 — [ container-3] com.xxx.redis.demo.RedisReceiver2 : Value: 我是消息2 好了Redis 订阅发布的教程到此为止。接下来我们看下如何用它来替代 Etcd 的业务情景
这之前我们先大概聊下 Etcd 的 2 个要点
Etcd 消息事件类型Etcd 持久层数据
那么问题来了Redis 虽然具备基本的消息订阅发布但是如何契合 Etcd 的这 2 点特性我们目前给出对应的解决方案是
使用 Redis K-V 的 value 作为 Etcd 消息事件类型使用 MySQL 作为 Etcd 持久层数据字段 id 随机 UUID、字段 key 对应 Etcd key、字段 value 对应 Etcd value这样做的一个好处是无需重构数据结构
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS 0;DROP TABLE IF EXISTS t_redis_msg;
CREATE TABLE t_redis_msg (
id varchar(32) NOT NULL,
key varchar(255) NOT NULL,
value longtext,
PRIMARY KEY (id)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4;SET FOREIGN_KEY_CHECKS 1;
所以如果想平替 Etcd 的事件类型和持久层数据的解决方案需要 MySQL Redis 结合接下来直接上代码…… Redis MySQL 整合
application.yml升级
spring:application:name: redis-demodatasource:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/db_demo?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driverhikari:connection-test-query: SELECT 1idle-timeout: 40000max-lifetime: 1880000connection-timeout: 40000minimum-idle: 1validation-timeout: 60000maximum-pool-size: 20
RedisMsg.java
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;/** author Lux Sun* date 2021/2/19/
Data
SuperBuilder
NoArgsConstructor
AllArgsConstructor
TableName(value t_redis_msg, autoResultMap true)
public class RedisMsg {TableId(type IdType.ASSIGN_UUID)private String id;TableField(value key)private String key;private String value;
}
RedisMsgEnum.java
/** author Lux Sun* date 2022/11/11/
public enum RedisMsgEnum {PUT(PUT),DEL(DEL);private String code;RedisMsgEnum(String code) {this.code code;}public String getCode() {return code;}}
RedisMsgService.java
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;/** author Lux Sun* date 2020/6/16/
public interface RedisMsgService extends IServiceRedisMsg {/** 获取消息* param key/RedisMsg get(String key);/** 获取消息列表* param key/MapString, String map(String key);/** 获取消息值* param key/String getValue(String key);/** 获取消息列表* param key/ListRedisMsg list(String key);/** 插入消息* param key* param value/void put(String key, String value);/** 删除消息* param key/void del(String key);
}
RedisMsgServiceImpl.java
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/** author Lux Sun* date 2020/6/16/
Slf4j
Service
public class RedisMsgServiceImpl extends ServiceImplRedisMsgDao, RedisMsg implements RedisMsgService {Resourceprivate RedisMsgDao redisMsgDao;Resourceprivate RedisUtil redisUtil;/** 获取消息** param key/Overridepublic RedisMsg get(String key) {LambdaQueryWrapperRedisMsg lqw new LambdaQueryWrapper();lqw.eq(RedisMsg::getKey, key);return redisMsgDao.selectOne(lqw);}/** 获取消息列表** param key/Overridepublic MapString, String map(String key) {ListRedisMsg redisMsgs this.list(key);return redisMsgs.stream().collect(Collectors.toMap(RedisMsg::getKey, RedisMsg::getValue));}/** 获取消息值** param key/Overridepublic String getValue(String key) {RedisMsg redisMsg this.get(key);return redisMsg.getValue();}/** 获取消息列表** param key/Overridepublic ListRedisMsg list(String key) {LambdaQueryWrapperRedisMsg lqw new LambdaQueryWrapper();lqw.likeRight(RedisMsg::getKey, key);return redisMsgDao.selectList(lqw);}/** 插入消息** param key* param value/Overridepublic void put(String key, String value) {log.info(开始添加 - key: {}value: {}, key, value);LambdaQueryWrapperRedisMsg lqw new LambdaQueryWrapper();lqw.eq(RedisMsg::getKey, key);this.saveOrUpdate(RedisMsg.builder().key(key).value(value).build(), lqw);redisUtil.putMsg(key);log.info(添加成功 - key: {}value: {}, key, value);}/** 删除消息** param key/Overridepublic void del(String key) {log.info(开始删除 - key: {}, key);LambdaQueryWrapperRedisMsg lqw new LambdaQueryWrapper();lqw.likeRight(RedisMsg::getKey, key);redisMsgDao.delete(lqw);redisUtil.delMsg(key);log.info(删除成功 - key: {}, key);}
}
RedisUtil.java升级
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;Slf4j
Component
public class RedisUtil {Resourceprivate RedisTemplate redisTemplate;/** 消息发送* param topic 主题* param message 消息/public void publish(String topic, String message) {redisTemplate.convertAndSend(topic, message);}/** 消息发送 PUT* param topic 主题/public void putMsg(String topic) {redisTemplate.convertAndSend(topic, RedisMsgEnum.PUT);}/** 消息发送 DELETE* param topic 主题/public void delMsg(String topic) {redisTemplate.convertAndSend(topic, RedisMsgEnum.DEL);}
} 演示 DEMO
RedisMsgController.java
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;/** author Lux Sun* date 2023/9/12/
RestController
RequestMapping(/redisMsg)
public class RedisMsgController {Resourceprivate RedisMsgService redisMsgService;PostMappingpublic String publish(RequestParam String topic, RequestParam String msg) {redisMsgService.put(topic, msg);return 发送成功: topic - msg;}
}
RedisMsgReceiver.java
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;Slf4j
Component
public class RedisMsgReceiver implements MessageListener {Resourceprivate RedisMsgService redisMsgService;Resourceprivate RedisMessageListenerContainer container;PostConstructpublic void init() {MessageListenerAdapter adapter new MessageListenerAdapter(this);container.addMessageListener(adapter, new PatternTopic(topic3.));}Overridepublic void onMessage(Message message, byte[] bytes) {String key new String(message.getChannel());String event new String(message.getBody());String value redisMsgService.getValue(key);log.info(Key: {}, key);log.info(Event: {}, event);log.info(Value: {}, value);}
}
测试
curl –location 127.0.0.1:7077/redisMsg
–header Content-Type: application/x-www-form-urlencoded
–data-urlencode topictopic3.msg
–data-urlencode msg我是消息3
结果
2023-11-16 10:24:35.721 INFO 43794 — [nio-7077-exec-1] c.c.redis.demo.RedisMsgServiceImpl : 开始添加 - key: topic3.msgvalue: 我是消息3
2023-11-16 10:24:35.935 INFO 43794 — [nio-7077-exec-1] c.c.redis.demo.RedisMsgServiceImpl : 添加成功 - key: topic3.msgvalue: 我是消息3
2023-11-16 10:24:35.950 INFO 43794 — [ container-2] c.xxx.redis.demo.RedisMsgReceiver : Key: topic3.msg
2023-11-16 10:24:35.950 INFO 43794 — [ container-2] c.xxx.redis.demo.RedisMsgReceiver : Event: PUT
2023-11-16 10:24:35.950 INFO 43794 — [ container-2] c.xxx.redis.demo.RedisMsgReceiver : Value: 我是消息3
- 上一篇: 什么网站做优化最好?门户网站建设要点
- 下一篇: 什么学做网站锡林浩特网站建设开发
相关文章
-
什么网站做优化最好?门户网站建设要点
什么网站做优化最好?门户网站建设要点
- 技术栈
- 2026年04月20日
-
什么网站做详情页好北京的制作网站的公司在哪里
什么网站做详情页好北京的制作网站的公司在哪里
- 技术栈
- 2026年04月20日
-
什么网站做淘宝素材比较好宁夏网站建设报价
什么网站做淘宝素材比较好宁夏网站建设报价
- 技术栈
- 2026年04月20日
-
什么学做网站锡林浩特网站建设开发
什么学做网站锡林浩特网站建设开发
- 技术栈
- 2026年04月20日
-
什么样 个人网站 备案南京图文广告公司
什么样 个人网站 备案南京图文广告公司
- 技术栈
- 2026年04月20日
-
什么样的网站结构适合做seo西安官网seo价格
什么样的网站结构适合做seo西安官网seo价格
- 技术栈
- 2026年04月20日
