Redis real battle - data structure List real battle queue feature realizes message multi thread broadcast notification

Posted by stevietee on Thu, 06 Feb 2020 05:29:49 +0100

Overview: the related content of this series of blog articles comes from the actual combat course recorded by debug in person: Introduction to Redis technology and application scenario practice (SpringBoot2.x + red packet system design and practice) , interested partners can click to learn by themselves (after all, mastering technology in the form of video will be faster!) Original link: Redis practice (4) - queue feature of data structure List practice to realize message multithreaded broadcast notification , technical column of the article: Introduction and practice of Redis Technology

Absrtact: the management back end of e-commerce platform generally has two roles that users can use, one is system administrator, the other is the seller / merchant of the platform. For merchants, managing their own products is a common thing in daily work, while for system administrator, sometimes it is necessary to issue some activity announcements to inform merchants to sign up We will implement the broadcast notification function of announcement message based on the queue feature of List!

Content: in the previous article, we introduced the data structure ~ List list of Redis, briefly introduced its basic features and how to realize the orderly storage of "merchants" when adding goods under the e-commerce application back-end management platform, and how to display it in the form of sequence table! (article link: Redis practice (3) - data structure List practice I: orderly storage of commodity information)

Among them, we show you the flow chart of the List list when storing and obtaining data. I don't know if you remember, as shown in the following figure:

It can be seen from the figure that when we add data to the Redis List, the data flow has the "first in, first out" feature, that is, the so-called "FIFO" (a bit of Queue feature!) Yes, and the data is compact, one by one!

That is to say, when we add data to the List of Redis, we can add it to the List of Redis in the way of "LPush is to add data from the left", and then use the way of "LPop is to eject data from the left" or "RPop is to eject data from the right" to obtain the orderly stored List data!

Knowing the data storage and reading process of List, we almost know the code implementation in the actual project development.

Next, we use "e-commerce application platform administrator, after publishing the activity announcement information on the platform, in addition to inserting the announcement information into the database DB, at the same time, LPush will insert it into the List list of Redis in the cache, and turn on timing detection at the other end of the interface to detect whether there is any announcement information in the List Redis specified in the cache at any time. If there is, RPO will be adopted P will pop up the announcement information and send it to the merchant by email! " , as shown in the following figure:

Next, let's enter into the code combat!

(1) First of all, of course, a "notification information table" is needed. Its complete DDL (data definition language) is as follows:

CREATE TABLE `notice` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'Notice title',
  `content` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT 'content',
  `is_active` tinyint(4) DEFAULT '1',
   PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COMMENT='Announcement';

(2) Then, of course, we need to develop a Controller (we have developed it above)! In the Controller, we need to set up a request method to add "announcement information" to the platform administrator. After receiving the announcement information, the request method needs to plug it into the database DB, and at the same time, it needs to LPush an announcement information to the List of Redis to be monitored and detected! The complete source code is as follows:

    //The platform sends notices to all merchants
    @RequestMapping(value = "/notice/put",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public BaseResponse putNotice(@RequestBody @Validated Notice notice, BindingResult result){
        String checkRes=ValidatorUtil.checkResult(result);
        if (StrUtil.isNotBlank(checkRes)){
            return new BaseResponse(StatusCode.Fail.getCode(),checkRes);
        }
        BaseResponse response=new BaseResponse(StatusCode.Success);
        try {
            log.info("--The platform sends a notice to each merchant:{}",notice);

            listService.pushNotice(notice);
        }catch (Exception e){
            response=new BaseResponse(StatusCode.Fail.getCode(),e.getMessage());
        }
        return response;
    }

(3) Next, we need to develop the Service corresponding to the Controller, whose responsibility is to deal with the real business logic of course, that is, when "add completion notification information", it is responsible for adding the product information to the DB database, and adding it to the List list of Redis. The complete source code is as follows:

    @Autowired
    private NoticeMapper noticeMapper;

    //Create notice
    @Transactional(rollbackFor = Exception.class)
    public void pushNotice(Notice notice) throws Exception{
        if (notice!=null){
            notice.setId(null);
            //TODO: insert notification information into database DB
            noticeMapper.insertSelective(notice);
            final Integer id=notice.getId();

            if (id>0){
                //TODO: put it into the List (queue) to be pulled to asynchronously notify the mailbox of different merchants - applicationevent & listener; rabbitmq; JMS
                ListOperations<String,Notice> listOperations=redisTemplate.opsForList();
                listOperations.leftPush(Constant.RedisListNoticeKey,notice);
            }
        }
    }

(4) After that, we need to create a "scheduled task scheduler" for "near real time" detection of whether the List in Redis has notification announcement information. If so, take out its RPop, and send it to "platform merchants" in the form of multi-threaded, so that they can sign up for relevant activities quickly! The complete source code is as follows:

/**
 * Redis List - consumer listeners for queues
 * @Author:debug (SteadyJack)
 * @Link: weixin-> debug0868 qq-> 1948831260
 * @Date: 2019/10/30 14:51
 **/
@Component
@EnableScheduling
public class ListListenerScheduler {

    private static final Logger log= 
    LoggerFactory.getLogger(ListListenerScheduler.class);

    private static final String listenKey= Constant.RedisListNoticeKey;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private EmailService emailService;

    //TODO: near real time timed task detection
    //@Scheduled(cron = "0/10 * * * * ?")
    @Scheduled(cron = "0/59 * * * * ?")
    public void schedulerListenNotice(){
        log.info("----Scheduled task scheduling queue listens, detects notification messages, listens list Data in");

        ListOperations<String,Notice> listOperations=redisTemplate.opsForList();
        Notice notice=listOperations.rightPop(listenKey);
        while (notice!=null){
            //TODO: email to all merchants
            this.noticeUser(notice);

            notice=listOperations.rightPop(listenKey);
        }
    }

    //TODO: send notifications to different merchants
    @Async("threadPoolTaskExecutor")
    private void noticeUser(Notice notice){
        if (notice!=null){
            //TODO: query and obtain all merchant information
            List<User> list=userMapper.selectList();

            //TODO: thread pool / multithreading triggering mass mailing
            try {
                if (list!=null && !list.isEmpty()){
                    ExecutorService executorService=Executors.newFixedThreadPool(4);
                    List<NoticeThread> threads= Lists.newLinkedList();

                    list.forEach(user -> {
                        threads.add(new NoticeThread(user,notice,emailService));
                    });

                    executorService.invokeAll(threads);
                }
            }catch (Exception e){
                log.error("Near real time timed task detection-Send notifications to different merchants-Law two-Thread pool/Multithreading trigger-Exception occurred:",e.fillInStackTrace());
            }
        }
    }
}

(5) At this point, our code practice is over. At last, we will enter the test phase based on Postman, which can be summarized in several figures:

Finally, look at the email box, you can see that you have received the email:

Well, we've introduced this article here. I suggest that you should follow the sample code provided in this article, and only after it can you know how to use it, otherwise you will become a "talker"!

Students who are interested in Redis related technology stacks and practical application scenarios can go to the course center of the technology community built by Debug to learn and watch: http://www.fightjava.com/web/index/course/detail/12 !

Other related technology, interested small partners can pay attention to the technical public number at the bottom of debug, or add WeChat debug (debug0868), pull you into the WeChat technology exchange group. Learn and grow together!

Supplement:

1. The relevant source code involved in this article can be check ed at this address for viewing and learning: https://gitee.com/steadyjack/SpringBootRedis

2. At present, debug has organized and recorded the content involved in this article into a video tutorial. Interested partners can go to watch and learn: http://www.fightjava.com/web/index/course/detail/12

3, pay attention to the technical WeChat public number of debug. The latest technical articles, courses and technical columns will be released in the public address for the first time.

Published 130 original articles, won praise 239, visited 610000+
His message board follow

Topics: Redis Database RabbitMQ