package com.moshi.receptionist.redis.pub; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.moshi.receptionist.redis.common.Constants; import com.moshi.receptionist.redis.common.exception.JedisUselessException; import com.moshi.receptionist.redis.common.util.JedisPoolUtil; import redis.clients.jedis.Jedis; public class PPubClient { private static final Logger log = LoggerFactory.getLogger(PPubClient.class); /** * 发布的每条消息,都需要在“订阅者消息队列”中持久 * @param message * @throws JedisUselessException */ private void put(String message,String channel,int offline_time_day) throws JedisUselessException{ DateFormat df = new SimpleDateFormat("yyyyMMdd"); String key =Constants.MESSAGE_BOX+channel+":"+df.format(new Date()); Jedis jedis = JedisPoolUtil.getResource(); try { if(!jedis.exists(key)){ jedis.rpush(key, message); jedis.expire(key, 60*60*24*offline_time_day);//不是那么精确,但是总比没有好 }else{ jedis.rpush(key, message); } } catch (Exception e) { log.error("pub message to MESSAGE_BOX error {}.",e.getMessage()); throw new JedisUselessException(); }finally{ JedisPoolUtil.returnResource(jedis); } } public void pub(String channel,String message,int offline_time_day) throws JedisUselessException{ //每个消息,都有具有一个全局唯一的id //txid为了防止订阅端在数据处理时“乱序”,这就要求订阅者需要解析message Jedis jedis = JedisPoolUtil.getResource(); try { Long txid = jedis.incr(Constants.MESSAGE_TXID+channel); String content = txid + "/" + message; //非事务 this.put(content,channel,offline_time_day); Set<String> localtions = findLocations(channel); for(String localtion:localtions){ if(log.isDebugEnabled()){ log.debug("publish {} to location {}.",channel,localtion); } jedis.publish(localtion, txid+"/"+channel);//为每个消息设定id,最终消息格式1000/channel } } catch (Exception e) { log.error("publish location error {}.",e.getMessage()); throw new JedisUselessException(); }finally{ JedisPoolUtil.returnResource(jedis); } } public Set<String> findLocations(String channel) throws JedisUselessException{ String pattern = Constants.SUBSCRIBE_CENTER+"*"+channel; Jedis jedis = JedisPoolUtil.getResource(); Set<String> keys = new HashSet<String>(1); try { keys = jedis.keys(pattern); } catch (Exception e) { log.error("find locations error {}.",e.getMessage()); throw new JedisUselessException(); }finally{ JedisPoolUtil.returnResource(jedis); } Set<String> locations = new HashSet<String>(1);//期望查询上来的只有1个 for(String member:keys){ String location = member.split(":")[1]; locations.add(location); } return locations; } public void close(String channel) throws JedisUselessException{ Jedis jedis = JedisPoolUtil.getResource(); try { jedis.publish(channel, "quit"); jedis.del(channel);//删除 } catch (Exception e) { log.error("close channel error {}.",e.getMessage()); throw new JedisUselessException(); }finally{ JedisPoolUtil.returnResource(jedis); } } }