从头开始学Redisson--------分布式集合之映射缓存(MapCache)

x33g5p2x  于2021-12-28 转载在 其他  
字(3.2k)|赞(0)|评价(0)|浏览(798)

一、缓存映射(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秒后触发过期事件,监听器监听到邮件。

相关文章