public AppResult AddItem(TbItem item, TbItemDesc itemDesc) {
IDUtils idUtils=new IDUtils();
Long itemId=idUtils.nextId();
Date date=new Date();
item.setId(itemId);
item.setCreated(date);
item.setUpdated(date);
itemDesc.setCreated(date);
itemDesc.setUpdated(date);
itemDesc.setItemId(itemId);
int ItemCount=itemMapper.insertSelective(item);
int ItemDescCount=itemDescMapper.insertSelective(itemDesc);
if (ItemCount!=1||ItemDescCount!=1){
throw new AppExeption(201,"添加失败");
}
SolrTbItem solrTbItem=new SolrTbItem();
solrTbItem.setItemTitle(item.getTitle());
solrTbItem.setItemCategoryName("123");
solrTbItem.setItemImage(item.getImage());
solrTbItem.setId(itemId);
solrTbItem.setItemPrice(item.getPrice());
solrTbItem.setItemSellPoint(item.getSellPoint());
//添加数据库
//添加到solr中,但需要通过消息队列
jmsTemplate.convertAndSend("tym_002",JsonUtils.objectToJson(solrTbItem));
return new AppResult(true,200,"添加成功",null);
}
@JmsListener(destination = "tym_002",containerFactory = "jmsQueryListenerFactory")
public void testreceiveQueue(TextMessage textMessage, Session session) throws Exception {
SolrTbItem solrTbItem=null;
try {
String id=textMessage.getJMSMessageID();
System.out.println(id);
if (redisTemplate.opsForValue().setIfAbsent(textMessage.getJMSMessageID(),"1")==false){
return;
}
solrTbItem= JsonUtils.jsonToPojo(textMessage.getText(),SolrTbItem.class);
int i=1/0;
AppResult result=searchService.addTbitem(solrTbItem);
if (result.isSuccess()==false){
throw new AppExeption();
}
System.out.println("成功添加");
textMessage.acknowledge();
redisTemplate.delete(textMessage.getJMSMessageID());
} catch (Exception e) {
System.out.println("存入redis 等待补偿系统");
redisTemplate.delete(textMessage.getJMSMessageID());
//补偿把item存到redis中,然后利用任务系统读取key keys values 中的keys传递给Jms补偿监听器
//把keys读取出来并遍历,然后调用服务添加到solr中。
redisTemplate.opsForHash().put("search_bc_add",textMessage.getJMSMessageID(),solrTbItem);
System.out.println("将整个消息队列放入redis的hash列表中,名为search_bc_add,等待消息系统取出补偿。。");
textMessage.acknowledge();
}
}
@Scheduled(cron = "*/10 * * * * ?")
public void searchItemBcTask(){
//先判断redis里面有没有该队列
//取出该队列且根据长度和是否为空判断是否要发送补偿消息进补偿队列
Set<String> keys=redisTemplate.opsForHash().keys("search_bc_add");
if (keys!=null&&keys.size()>0){
System.out.println("发现有补偿消息");
jmsTemplate.convertAndSend("cs1901_bc_search_add", JsonUtils.objectToJson(keys));
}else {
System.out.println("无---------");
}
}
//该监听器监听补偿 即是第一个监听器未添加进solr成功,被任务系统查出,查找的消息队列
@JmsListener(destination = "cs1901_bc_search_add",containerFactory = "jmsQueryListenerFactory")
public void BcSearchAdd(TextMessage textMessage, Session session) throws Exception {
//首先考虑幂等性 问题,无则存入redis 有则return
//监听cs1901_bc_search_add 队列,若有则处理
// 处理方法,遍历keys,查询redis中存的tbitem 并调用searchService的方法插入solr索引库
//成功与否都删除redis中的键,全部键插入完成删除整个hash列表
//未成功打印到分布式日志中
try {
if (redisTemplate.hasKey(textMessage.getJMSMessageID())==true){
System.out.println("该数据被别的监听器锁住");
return;
}
System.out.println("将补偿消息锁住");
redisTemplate.opsForValue().set(textMessage.getJMSMessageID(),"");
Set keys=JsonUtils.jsonToPojo(textMessage.getText(), Set.class);
for (Object key : keys) {
SolrTbItem solrTbItem= (SolrTbItem) redisTemplate.opsForHash().get("search_bc_add",key);
System.out.println(solrTbItem.getId());
AppResult result=searchService.addTbitem(solrTbItem);
if (result.isSuccess()==false){
throw new AppExeption();
}
redisTemplate.opsForHash().delete("search_bc_add",key);
System.out.println("redis删除小键");
}
redisTemplate.delete("search_bc_add");
System.out.println("redis删除hash");
redisTemplate.delete(textMessage.getJMSMessageID());
System.out.println("redis删除该消息,解除锁");
textMessage.acknowledge();
}catch (Exception e){
//此处打印
textMessage.acknowledge();
}
}
第一次的监听服务的补偿暂时未做重试,由于考虑到定义次数的线程不安全性。
Springboot与ActiveMQ、Solr、Redis中分布式事物的初步探索
原文:https://www.cnblogs.com/tanyiming/p/11127991.html