Core requirements

In a project, I met the need to search hot word statistics, and I used Sorted Set, one of Redis’ five data types. At present, there are two statistics to be collected: “top10 hot search words of the day” and “top10 hot search words of the week”.

As for the statistical methods of these two data, two realization methods have come to mind at present:

  1. Two Sorted Set implementations of Redis, one Sorted Set A statistics day, 0 top10 points recorded in MySQL, Sorted Set zero. A Sorted Set B statistics week, every Sunday top10 recorded in MySQL, Sorted Set B zero.
  2. Just use a Sorted Set to record the hot search terms of the day. The 0 top10 points are recorded in MySQL and Sorted Set is cleared. By Sunday, there will be 7 by 10 lines. After traversing these 7 * 10 lines, each convenience is recorded in Sorted Set. After traversing all the lines, top10 is extracted from Sorted Set and recorded in the statistics table of weekly hot words in MySQL.

Sorted Set is a Redis data structure. Method 1 takes up two copies of memory, one for the current day and one for the current week. Method 2 will increase the complexity of the system, and may cause a large number of calculations in a short period of time when calculating the weekly table (of course, scheduled tasks can be used, and the weekly table statistics can be carried out in the early morning).

Finally, we choose scheme 1, which is clear and clear for separate maintenance.

As for the memory footprint, 1MB = 1048576 bytes, based on saving one word for two words, 1MB can theoretically store 1048576/2/8 = 65,536 non-repeating search keywords (of course using Sorted Set definitely takes up more space than pure words). If you invest a little more memory, you can still save a lot of it, and it usually lasts until the end of the week. Typical CRUD projects don’t have to worry about memory footprint.

The relevant knowledge involved in the question

In a project, I encountered the need to search the statistics of hot words. I used one of Redis’s five major data types, the Sorted Set implementation.

Sorted set Redis sorted set

Redis ordered collections, like collections, are collections of string elements and do not allow duplicate members.

The difference is that each element is associated with a double score. Redis uses scores to sort the members of a collection from smallest to largest.

The members of an ordered set are unique, but the score can be repeated.

Collections are implemented by hashing tables, so adding, deleting, and searching are O(1) complexity. The maximum number of members in a collection is 232-1 (4294967295, each collection can store more than 4 billion members). Defined by: Rookie tutorial

As shown above, Redis’s Sorted Set comes with Sorted functionality.

The operation method is also relatively simple. In this project, the core is two methods:

Zincrby, for a Sorted Set, adds x to the score if it exists (x is optional) and creates a member with a score of 1 if it doesn’t.

Zrevrange to query the Sorted Set for the specified range of values. In the ordered set returned, the one with the highest score is in the front. This method does not have to worry about out-of-bounds errors with start and end for the specified scope.

In a StringRedisTemplate, the Sorted Set is called a ZSet. For more information on how to use Redis’s Soeted Set, see redis’s ZSet Data Structure Usage posture

code

Service example code:

@Service("redisService")
public class RedisServiceImpl implements RedisService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    /** * use Sorted Set to record the keyword * zincrby command. For a Sorted Set, add x to the score if it exists, and create a Sorted Set with a score of 1 ** if it does not@paramKeyword Searches for keywords */
    @Override
    public void searchZincrby(String keyword) {
        Sorted Set = sortedSetName = sortedSetName = sortedSetName = sortedSetName = sortedSetName = sortedSetName = sortedSetName = sortedSetName = sortedSetName
        String sortedSetName = "searchHotWord";
        // See the annotation of this method for the meaning of x
        double x = 1.0;
        redisTemplate.opsForZSet().incrementScore(sortedSetName, keyword, x);
    }

    /** * zrevrange: select * from Sorted Set ** zrevrange: select * from Sorted Set ** zrevrange: select * from Sorted Set ** zrevrange: select * from Sorted Set **@paramStart Indicates the start position of the query range *@paramEnd Indicates the end position *@return* /
    @Override
    public Set<ZSetOperations.TypedTuple<String>> queryTopSearchHotWord(Integer start, Integer end) {
        String sortedSetName = "searchHotWord";
        Set<ZSetOperations.TypedTuple<String>> resultSet =  redisTemplate.opsForZSet().reverseRangeWithScores(sortedSetName, start, end);
        returnresultSet; }}Copy the code

Controller sample code

@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisService redisService;
    
    /** * Test redis record keyword **@paramKeyword Searches for keywords *@return* /
    @GetMapping("/test_search")
    public ResultVO testSearch(@RequestParam("keyword") String keyword) {
        redisService.searchZincrby(keyword);
        // ResultVO and ResultVOUtil are custom classes. To show the results, ignore them when reading
        return ResultVOUtil.success(1."test-return");
    }

    /** * test redis to query the specified range of hot words **@paramStart Indicates the start position of the query range *@paramEnd Indicates the end position *@return* /
    @GetMapping("/test_query_top_search_hot_word")
    public ResultVO testQueryTopSearchHotWord(@RequestParam("start") Integer start,
                                              @RequestParam("end") Integer end) {
        Set<ZSetOperations.TypedTuple<String>> resultSet =  redisService.queryTopSearchHotWord(start, end);
        // ResultVO and ResultVOUtil are custom classes. To show the results, ignore them when reading
        return ResultVOUtil.success(1."success", resultSet); }}Copy the code

Test how your code works

Simulate searching for some keywords:

Use RDM to check the storage status of reids, search hot words already exist in redis a Sorted Set named searchHotWord:

Query result:

One more thing

The ZRevRange method does not have to worry about out-of-bounds errors with start and end for the specified range.

The Sorted Set used for testing has a total of eight data points, and is deliberately specified to have start and end outside this range:

After testing, on the premise of ensuring that both start and end >=0, start and end have no transgression error problem.