如何在分布式环境中同步solr索引库和缓存信息
天气依旧很好,主要是凉快。老习惯,我在北京向各位问好。
搜索无处不在,相信各位每天都免不了与它的亲密接触,那么我想你确实有必要来了解一下它们,就上周在公司实现的一个小需求来给各位分享一下:如何在分布式环境下同步索引库?
需求分析
公司数据库中的数据信息每天都免不了增、删、改操作,在执行这些简单的更新操作时,我们不仅将变更后的数据要更新到数据库中,同时还要马上同步索引库中的数据,有的时候还要同步一下缓存中的数据(本文只分享如何同步solr索引库)。
分析方案
当我们在后台管理系统中触发了更新操作时,不会紧跟着调用同步功能去更新索引库和缓存这种机制去实现,因为耦合性太高了,容易影响正常的业务流程。那么,既然我们不做,做的话就要影响业务,所以我们就有必要请一位私人秘书来替我们完成同步操作了,既然请了秘书,就没必要再去关心同步操作,而是我们只需要在更新完数据后通知这位秘书,让它去完成同步操作,岂不更妙?好了,说了这么久,这位秘书就是英俊潇洒不可或缺的消息队列——MQ,为什么使用它?主要还是开源、解耦。废话不说了,一起从简,开始上码。

哦,对了到这儿我就有必要说一下MQ的俩种使用模式,因为这个确实有点用,我就爬过这坑。主要分为2种:点对点(Queue)和发布\订阅(Topic)模式。

从上图可以看出,这俩种模式最主要的区别就是发送出去的消息可以由多少个消费者来接受,很明显:
发布\订阅模式:需要一个生产者发送消息到主题版块(Topic)中,可以有多个消费者订阅该版块来接受消息。消费者接受消息时,必须处于运行状态,而且只能接受运行之后的消息。
点对点模式:需要一个生产者发送消息到队列版块(Queue)中,只能有一个消费者从该队列(Queue)中接受该消息。生产者发送消息时,消费者不需要处于运行状态。
好,明确这点就够了,我们先用起来,至于它的一些细节,你们自己去找找资料好好读读,因为本人也是初次使用到,后期有机会再和大家共勉。
一路走好,码到成功
步骤一:安装MQ(activeMQ)
狠简单,解压即用。如有需要请参考http://www.cnblogs.com/1315925303zxz/p/6377551.html。
步骤二:spring整合MQ
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.136.139:61616"/>
</bean>
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
</bean> <!-- 生产者 -->
<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<!--这个是队列目的地:(俩种配置方式)
一、点对点模式:需要一个生产者发送消息到队列版块(Queue)中,只能有一个消费者从该队列(Queue)中接受该消息。
【生产者发送消息时,消费者不需要处于运行状态】。
二、发布订阅模式:需要一个生产者发送消息到主题版块(Topic)中,可以有多个消费者订阅该版块来接受消息。
【生产者发送消息时,消费者必须处于运行状态,而且只能接受运行之后的消息】。
-->
<!-- 点对点模式 -->
<!-- <bean id="testQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>test-queue</value>
</constructor-arg>
</bean> -->
<!-- 发布订阅模式 -->
<bean id="testTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="test-topic"/>
</bean> <!-- 消费者 -->
<!-- 配置自定义消息监听器 -->
<bean id="myMessageListener" class="cn.soa.mq.MyMessageListener"></bean>
<!-- 配置MessageListenerContainer -->
<bean id="jmsContainer"
41 class="org.springframework.jms.listener.DefaultMessageListenerContainer">
42 <property name="connectionFactory" ref="connectionFactory"/>
43 <property name="destination" ref="testTopic"/> <!-- 这儿注意生产者使用的是那种模式并且用哪个队列来发送消息的 -->
44 <property name="messageListener" ref="myMessageListener"/>
45 </bean>
步骤三:执行更新操作时,通知秘书去同步索引库、缓存等
@Autowired
private ItemMapper itemMapper;
//消息队列
@Autowired
private JmsTemplate jmsTemplate;
@Resource(name="testTopic")
private Destination testTopic;
@Override
public int saveItem(Item item) {
final String itemId = UUIDUtils.getUUID();
if(StringUtil.isNullOrBlank(item.getId())){
//如果商品主键为空,则设置一个ID
item.setId(itemId);
}
if(StringUtil.isNullOrBlank(String.valueOf(item.getCreateTime()))){
//如果创建时间为空,则设置当前时间为创建时间
item.setCreateTime(DateTimeUtils.getCurrentDate());
}
int save = itemMapper.saveItem(item);
if(save == 1){
//如果新增商品成功,则发送商品ID到消息队列中,目的同步索引库、缓存等
jmsTemplate.send(testTopic, new MessageCreator(){
23 @Override
24 public Message createMessage(Session session) throws JMSException {
25 // 将商品ID发送出去
26 logger.error("发送新增商品的ID到MQ消息队列中:{}==============================");
27 TextMessage message = session.createTextMessage(itemId);
28 return message;
29 }
30 });
}
return save;
}
步骤四:使用MQ监听器同步索引库(监听器需在spring配置文件中配置)
public class MyMessageListener implements MessageListener{
private final static Logger logger = LoggerFactory.getLogger(MyMessageListener.class);
@Autowired
private SolrServer solrServer;
@Autowired
private ItemService itemService;
/**
* 根据监听到的商品ID来同步索引库数据。
*/
@Override
public void onMessage(Message message) {
logger.info("============开始同步索引库================");
// 根据不同业务逻辑进行相应处理
if(message instanceof TextMessage){
try {
TextMessage textMessage = (TextMessage) message;
21 String ID = textMessage.getText(); //监听到新商品ID
Item newItem = itemService.findItemById(ID); //根据新主键查询到商品信息
// 将商品数据封装到SolrInputDocument对象
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", newItem.getId());
doc.addField("product_catalog_name", "忠哥系列");
doc.addField("product_price", newItem.getPrice());
doc.addField("product_name", newItem.getItemName());
// 添加到索引库
solrServer.add(doc);
// 提交
solrServer.commit();
} catch (Exception e) {
logger.error("同步索引库失败:{}"+e.getMessage());
}
}
}
}
步骤五:校验数据是否同步成功,马上就可以在索引库中搜到我们刚刚新增的信息

参考:
http://www.cnblogs.com/1315925303zxz/p/6254016.html 仿京东站内搜索案例
http://www.cnblogs.com/1315925303zxz/p/6372004.html solrcloud集群环境搭建
与君共勉!每天都有新技能!
如何在分布式环境中同步solr索引库和缓存信息的更多相关文章
- ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据
引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们 ...
- 【Zookeeper系列】ZooKeeper管理分布式环境中的数据(转)
原文地址:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...
- Java多线程编程——并发编程原理(分布式环境中并发问题)
在分布式环境中,处理并发问题就没办法通过操作系统和JVM的工具来解决,那么在分布式环境中,可以采取一下策略和方式来处理: 避免并发 时间戳 串行化 数据库 行锁 统一触发途径 避免并发 在分布式环境中 ...
- ZooKeeper系列(5):管理分布式环境中的数据
引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知 识,理解起来比较抽象所以还需要借助一些应用场景,来帮我 ...
- ZooKeeper管理分布式环境中的数据
Reference: http://www.cnblogs.com/wuxl360/p/5817549.html 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...
- 分布式服务框架 Zookeeper — 管理分布式环境中的数据
本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们理解. ...
- 高并发分布式环境中获取全局唯一ID[分布式数据库全局唯一主键生成]
需求说明 在过去单机系统中,生成唯一ID比较简单,可以使用MySQL的自增主键或者Oracle中的sequence, 在现在的大型高并发分布式系统中,以上策略就会有问题了,因为不同的数据库会部署到不同 ...
- 【转】Java多线程编程(十)-并发编程原理(分布式环境中并发问题)
转载地址:http://blog.csdn.net/leicool_518/article/details/42268947 在分布式环境中,处理并发问题就没办法通过操作系统和JVM的工具来解决,那么 ...
- ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据(转)
转载来源:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...
随机推荐
- Linux中mysql乱码问题
注意: 关于utf8和gbk的区别详细见:linux中文乱码问题解决办法 http://www.linuxidc.com/Linux/2010-04/25757.htm ,下面的配置中根据自己要求选择 ...
- 神经网络与深度学习笔记 Chapter 3.
交叉熵 交叉熵是用于解决使用二次代价函数时当单个神经元接近饱和的时候对权重和bias权重学习的影响.这个公式可以看出,当神经元饱和的时候,sigma的偏导接近于0,w的学习也会变小.但是应用交叉熵作为 ...
- 在学习泛型时遇到的困惑经常与func<T,U>混淆
在学习泛型时遇到的困惑经常与func<T,U>混淆,总认为最后一个值是返回类型.现在区分一下,原来问题出在泛型委托上. C#委托的介绍(delegate.Action.Func.predi ...
- win10 安装 mysql解压版安装步骤
参考资料:win 10 安装 mysql 5.7 网址:http://blog.sina.com.cn/s/blog_5f39af320102wbk0.html 本文参考上面的网址的教程,感谢作者分享 ...
- Django 学习笔记(六)MySQL配置
环境:Ubuntu16.4 工具:Python3.5 一.安装MySQL数据库 终端命令: sudo apt-get install mysql-server sudo apt-get install ...
- mysql查看表结构2种方式对比
1.desc t_bookType; 2.show create table t_bookType; 相信大部分人还是喜欢第一种查看表结构方式.
- python专题-Mysql数据库(python2._+ Mysqldb)
Python使用MySQL数据库 MySQLdb驱动从2014年1月停止了维护. Python2 MySQLdb 一,安装mysql 如果是windows 用户,mysql 的安装非常简单,直接下载安 ...
- php精简完全小结(linux/laravel篇)
php官网:http://www.php.netphp版本: 查看:php -version说明:None-Thread Safe就是非线程安全,在执行时不进行线程(thread)安全检查:Threa ...
- jsp、freemarker、velocity区别详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt172 在java领域,表现层技术主要有三种:jsp.freemarker.v ...
- [转]Java se 7 最新特性研究(一)
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp81 从2006到现在等待了多年的jdk7终于发布了.这里将对它的一些 ...