Redis笔记(四)

前面一小节讲到了在抢票场景中使用Redis的分布式锁,接下来这个场景会相对的复杂一些,模拟博客网站,提供发布和点赞功能,用到了String,Hash,Set,Zset四种数据结构。具体要求如下:

  1. 提供发布、点赞、查看文章列表的功能
  2. 文章列表按照发布时间或者分值进行排序
  3. 每个用户点赞即可增加文章10点分值(分值的增加方式也可以是其它的,如评论、浏览量等)
  4. 文章只允许在发布后的三天内被点赞,超过三天就不能再点赞了
  5. 文章发布,默认自己给当前文章点赞

上面大概就是这次笔者写的案例需求,接下来看看代码,会有比较详细的注解说明

VoteController

@RestController
public class VoteController {
    @Autowired
    private ArticleService articleService;
	//发布文章
    @PostMapping("/publish")
    public void publishArticle(@RequestBody PublishArticleVO publishArticleVO) {
        articleService.publishArticle(publishArticleVO);
    }
    //点赞
    @PostMapping("/vote")
    public void vote(@RequestBody VoteVO vo) {
        articleService.vote(vo);
    }
    //按时间倒序查看文章列表
    @PostMapping("/list")
    public void list() {
        articleService.list();
    }
    //按文章分值倒序查看文章列表
    @PostMapping("/list_score")
    public void listScore() {
        articleService.listScore();
    }
}

ArticleService

@Service
public class ArticleService {
    //三天时间 -秒
    private Long THREE_DAY_SECONDS = 259200L;
    @Autowired
    private RedisUtils<Object> redisUtils;
//发布文章
    public void publishArticle(PublishArticleVO publishArticleVO) {
        Long artId = redisUtils.incr("artKey",1);
        String artKey = "art:" + artId;
        String voteKey = "vote:" + artId;
        //map保存文章的详细信息
        Map<String, Object> map = new HashMap<>(7);
        long time = System.currentTimeMillis() / 1000;
        map.put("artId",artId);
        map.put("artTitle", publishArticleVO.getTitle());
        map.put("artContent", publishArticleVO.getContent());
        map.put("url", publishArticleVO.getUrl());
        map.put("user", publishArticleVO.getUserId());
        map.put("time", String.valueOf(time));
        //默认自己点赞
        map.put("vote", 1);

        redisUtils.hmset(artKey, map);
        System.out.println("userId:"+publishArticleVO.getUserId()+"发布了artId:"+artId);
        //保存当前文章已经点赞的用户id,发布时默认给自己点赞
        redisUtils.sSet(voteKey, publishArticleVO.getUserId());
        //保存文章的发布时间
        redisUtils.zAdd("artTime", artKey, time);
        //保存文章的得分,自己点赞,加10分
        redisUtils.zAdd("score", artKey, 10L);
        System.out.println("userId:"+publishArticleVO.getUserId()+"对文章artId:"+artId+" 进行了点赞");
    }
//点赞
    public void vote(VoteVO vo) {
        String artKey = "art:" + vo.getArtId();
        String voteKey = "vote:" + vo.getArtId();
        //拿到文章的发布时间,判断是否超过三天
        Double artTime = redisUtils.zscore("artTime", artKey);
        if (artTime < System.currentTimeMillis() / 1000 - THREE_DAY_SECONDS) {
            System.out.println("artId:"+vo.getArtId()+"  已发布三天后无法参与投票");
            return;
        } else {
            //如果用户还未对该文章点赞,则允许点赞
            if (!redisUtils.sHasKey(voteKey, vo.getUserId())) {
                //加入set,表示该用户已经点赞
                redisUtils.sSet(voteKey, vo.getUserId());
                //文章点赞数+1
                redisUtils.hincr(artKey, "vote", 1);
                //分值+10
                redisUtils.zincr("score", artKey, 10);
                System.out.println("userId:"+vo.getUserId()+"对文章artId:"+vo.getArtId()+" 进行了点赞");
            } else {
                System.out.println("userId:" + vo.getUserId() + "无法对artId:"+vo.getArtId()+"重复投票");
            }
        }
    }
//按时间倒序查看文章列表
    public void list() {
        //按发布时间倒序查看前三篇文章
        Set artKey = redisUtils.range("artTime", 3, false);
        //遍历打印出来
        artKey.forEach(e -> {
            Map<String, Object> art = redisUtils.hmget((String)e);
            System.out.println("--------------"+e+"------------------");
            art.entrySet().forEach(m -> {
                System.out.println(m.getKey() + ": " + m.getValue());
            });
        });
    }
//按文章分值倒序查看文章列表
    public void listScore() {
        //按文章分值倒序查看前三篇文章
        Set artKey = redisUtils.range("score", 3,false);
        //遍历打印出来
        artKey.forEach(e -> {
            Map<String, Object> art = redisUtils.hmget((String) e);
            System.out.println("--------------"+e+"------------------");
            art.entrySet().forEach(m -> {
                System.out.println(m.getKey() + ": " + m.getValue());
            });
        });
    }
}

RedisUtils

@Component
public class RedisUtils<T> {
    @Resource(name = "redisTemplate")
    private RedisTemplate<String, T> redisTemplate;
//redis的操作类
    public long incr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }
    
    public boolean hmset(String key, Map<String, T> map) {
        redisTemplate.opsForHash().putAll(key, map);
        return true;
    }
    
    public long sSet(String key, T... values) {
        return redisTemplate.opsForSet().add(key, values);
    }
    
    public boolean zAdd(String key, T obj, double score) {
        return redisTemplate.opsForZSet().add(key, obj, score);
    }

    public Double zscore(String key,Object feild){
        return redisTemplate.opsForZSet().score(key, feild);
    }
    
    public boolean sHasKey(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }
    
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }
    
    public double zincr(String key, T feild, double by) {
        return redisTemplate.opsForZSet().incrementScore(key, feild, by);
    }
    
    public Set<T> range(String key, int size, boolean isAsc) {
        if (isAsc) {
            return redisTemplate.opsForZSet().range(key, 0, size-1);
        }
        return redisTemplate.opsForZSet().reverseRange(key, 0, size-1);
    }
    
    public Map<String, T> hmget(String key) {
        return redisTemplate.<String, T>opsForHash().entries(key);
    }
}

RedisConfig

@Configuration
public class RedisConfig {
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(lettuceConnectionFactory);
        // 这里可以给template加一些序列化的定制
        return template;
    }
}

PublishArticleVO

@Data
public class PublishArticleVO {
    /**
     * 用户id
     */
    private String userId;
    /**
     * 标题
     */
    private String title;
    /**
     * 文章内容
     */
    private String content;
    /**
     * url
     */
    private String url;
}

VoteVO

@Data
public class VoteVO {
    /**
     * 用户id
     */
    private String userId;
    /**
     * 文章的id
     */
    private String artId;
}

运行结果:

1.先发布6篇文章,每篇文章发布时自己默认会为文章点赞

在这里插入图片描述

2.检测是否能重复点赞
在这里插入图片描述

在这里插入图片描述

4.按时间倒序,列出前三篇文章

在这里插入图片描述

5.按文章的分值倒序,列出前三篇文章

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
狂神在他的Redis笔记中可能会涉及到一些内容,但是根据提供的引用内容,无法确定具体是哪些内容。可以使用自定义的配置文件来启动Redis服务,使用systemctl命令来启动和关闭服务。\[1\]在复杂的情况下,可以使用专业的消息中间件来进行订阅,但是需要注意如果订阅方的读取消息速度不够快,可能会导致消息积压,影响Redis的性能甚至导致崩溃。\[2\]Redis和Memcached一样,数据都是缓存在内存中,但是Redis会周期性地将更新的数据写入磁盘或记录文件,并通过主从复制实现数据同步。\[3\]如果你有具体的问题或需要更详细的信息,请提供更多的上下文。 #### 引用[.reference_title] - *1* *2* [Redis详细笔记](https://blog.csdn.net/qq_40087648/article/details/109808727)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [狂神说 Redis笔记](https://blog.csdn.net/DDDDeng_/article/details/108118544)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值