从头开始学Redisson--------分布式集合之映射缓存(MapCache)
一、缓存映射(MapCache)
Redisson的分布式的RMapCache Java对象在基于RMap
的前提下实现了针对单个元素的淘汰机制。同时仍然保留了元素的插入顺序。映射缓存(MapCache)它能够保留插入元素的顺序,并且可以指明每个元素的过期时间(专业一点叫元素淘汰机制)。另外还为每个元素提供了监听器,提供了4种不同类型的监听器。有:添加、过期、删除、更新四大事件。
二、实战
现在做一个模拟发送邮件的功能。现有如下m_email邮箱表。主要记录发送邮件的基础信息,以及判断是否延迟发送与其应该发送邮件的时间。
如下代码。首先判断用户希望的是延迟发送还是里立即发送。重点看延迟发送的分支代码。首先通过用户希望发送邮件的时间,计算这个发送时间与当前时间的差值,作为映射缓存(MapCache)的此封邮件的过期时间。
@Service
public class MailService ...
@Autowired
private RedissonClient redisson;
public void sendMail(Mail mail) throws ParseException {
mail.setId(null);
//是否延迟发送。0:立即发送,1:立即发送
if (mail.getIsDelay().equals("1") && StringUtils.isNotBlank(mail.getSendTime())) {
//解析发送时间成毫秒
Long sendTime = DateTransformTools.dateStrToMillis(mail.getSendTime(), null);
//计算出 未来发送的时间 与当前时间的 差值,作为元素的TTL过期时间
Long diffTime = sendTime - System.currentTimeMillis();
if (diffTime <= 0) {
LOGGER.error("发送时间必须大于当前时间");
throw new RuntimeException("发送时间必须大于当前时间");
}
//邮件对象入库
mailMapper.insertMail(mail);
//邮件对象入缓存
if (mail.getId() > 0) {
//缓存映射存放 邮件ID--发送者
RMapCache<Long, String> rMapCache = redisson.getMapCache(Constant.REDISSON_MAP_CACHE_EMAIL);
//通过缓存映射,为元素设定有效时间
rMapCache.put(mail.getId(), mail.getTos(), diffTime, TimeUnit.MILLISECONDS);
}
} else {
mailMapper.insertMail(mail);
LOGGER.info("立即发送邮件成功,发送ID:{}", mail.getId());
}
}
延迟发送
刚才为延迟发送的邮件计算出来它的过期时间,一旦此邮件过期,这就代表这封邮件应该在过期的那一刻发送,从而达到延迟发送邮件的目的。怎么发送呢?缓存映射(MapCache)为每个元素提供了过期事件。因此,需要为邮件增加过期事件监听器。
package com.tyzhou.mail.listener;
import com.tyzhou.Constant;
import com.tyzhou.mail.mapper.MailMapper;
import com.tyzhou.mail.modol.Mail;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.redisson.api.map.event.EntryEvent;
import org.redisson.api.map.event.EntryExpiredListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
@Component
public class MailListener implements ApplicationRunner, Ordered {
private static final Logger LOGGER = LoggerFactory.getLogger(MailListener.class);
@Autowired
private RedissonClient redisson;
@Autowired
private MailMapper mailMapper;
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
LOGGER.info("缓存映射MapCache延迟发送邮件启动");
sendMail();
}
@Override
public int getOrder() {
return 2;
}
private void sendMail() {
RMapCache<Long, String> rMapCache = redisson.getMapCache(Constant.REDISSON_MAP_CACHE_EMAIL);
rMapCache.addListener(new EntryExpiredListener<Long, String>() {
@Override
public void onExpired(EntryEvent<Long, String> event) {
/**
* 缓存映射缓存的是邮件对象的主键ID与邮箱接收人
* rMapCache.put(mail.getId(), mail.getTos(),diffTime, TimeUnit.MILLISECONDS);
*/
Long emailId = event.getKey();
Mail mail = mailMapper.selectByPrimaryKey(emailId);
if (mail != null) {
LOGGER.info("发送邮件主题:{},内容:{},接收人:{}", mail.getSubject(),
mail.getContent(), mail.getTos());
}
}
});
}
}
不想发送邮件了
延迟发送的邮件不想发送了,需要删除数据库里的邮件,然后再从缓存映射(MapCache)中清除此邮件的缓存。
public void delete(Long id) {
//删库
int res = mailMapper.delete(id);
if (res > 0) {
RMapCache<Long, String> rMapCache =
redisson.getMapCache(Constant.REDISSON_MAP_CACHE_EMAIL);
rMapCache.remove(id);
}
}
实现效果
发送的邮件入库并入缓存映射(MapCache ),指定邮件30秒后发送。30秒后触发过期事件,监听器监听到邮件。
你看我都这么努力的分享知识给你了,鼓励一下又何妨O(∩_∩)O
你的打赏是对我最好的支持!