第三章 Redis设计实战笔记

本文介绍了基于Redis设计的投票网站实战,包括应用场景、数据库设计、Redis实现和缓存设计,强调了Key设计思路和防重投策略。此外,还探讨了Redis+Lua限流实战,详细讲解了LUA语言、限流概念和实现。最后,展示了Redis+Lua在抢红包业务中的应用,包括业务需求、基础命令和Lua脚本实现。
摘要由CSDN通过智能技术生成

一、基于Redis设计的投票网站实战

1、应用场景实战

文章投票功能模块需求

  • 用户可以发表文章,发表时默认给自己的文章投了一票
  • 用户在查看网站时可以按评分进行排列查看
  • 用户也可以按照文章发布时间进行排序
  • 为节约内存,一篇文章发表后,7天内可以投票,7天过后就不能再投票了
  • 为防止同一用户多次投票,用户只能给一篇文章投一次票

2、关系数据库设计

文章基本信息表 t_article

article_id  title  content post_time user_id

文章票数与分值表 t_vote_data

article_id  votes  scores

文章投票详表 t_vote_details

article_id  vote_time  user_id

3、应用场景Redis实现

投票网站应用场景会使用到的Redis相关指令如下:

HASH类型命令:

hset  hincrBy  hgetAll   expire

SET集合命令:

sadd  smembers

ZSET集合命令:

zadd   zscore  zincrby  zrevrange

4、redis的Key设计思路

Key-Value键值对:比如set key value

key的设计:一般以业务、功能模块或表名开头,后跟主键(或能表示数据唯一性的值)

例子:用户模块,其中用户ID 001,用户名称hankin,那么Key如何设计?

set user:001:name hankin

key为 user:001:name

5、记录已投票用户,防重投

已对002文章投票过的用户,使用SET存储(无序,不能重复)

 

6、记录文章分值

使用ZSET记录文章投票分数,和按文章发布的时间戳(有序列,不能重复)

 

7、Redis缓存设计实战

 

8、缓存数据变化

1)004号用户对文章article:002投了1张票,文章的评分增加了400

 

2)004号用户对article:002文章投票后,会被追加到已投票用户名单里

 

9、代码环节

代码参考:redis-vote模块,git地址:https://gitee.com/hankin_chj/redis-platform.git

业务接口方法:

/**
 * 业务接口方法
 */
public interface RedisArticleService {
     public String postArticle(String title, String content, String link, String userId);
     public Map<String, String> hgetAll(String key);
     public void articleVote(String userId, String articleId);
     public String hget(String key, String votes);
     public List<Map<String,String>> getArticles(int page, String order);
}

文章发布代码:

/**
* 文章发布使用redis技术
*/
@Service
public class RedisArticleServiceImpl implements RedisArticleService {
   @Resource
   private JedisUtils jedis;
   /**
   * 文章提交发布
   * @param title 标题  内容  链接  用户ID
   * @return 文章的ID
   */
   @Override
   public String postArticle(String title, String content, String link, String userId) {
      //article:001
        String articleId = String.valueOf(jedis.incr("article:")); // articleId=1
        //投票键: voted:
        String voted = "voted:" + articleId;
        jedis.sadd(voted, userId);
        jedis.expire(voted, Constants.ONE_WEEK_IN_SECONDS);
        long now = System.currentTimeMillis() / 1000;
        String article = "article:" + articleId;
        HashMap<String,String> articleData = new HashMap<String,String>();
        articleData.put("title", title);
        articleData.put("link", link);
        articleData.put("user", userId);
        articleData.put("now", String.valueOf(now));
        articleData.put("votes", "1");
        jedis.hmset(article, articleData);
        jedis.zadd("score:info", now + Constants.VOTE_SCORE, article);
        jedis.zadd("time:", now, article);
        return articleId;
   }
   /**
   * 文章投票
   * @param  userId 用户ID 文章ID(article:001)  //001
   */
   @Override
   public void articleVote(String userId, String article) {
      //计算投票截止时间
        long cutoff = (System.currentTimeMillis() / 1000) - Constants.ONE_WEEK_IN_SECONDS;
        //检查是否还可以对文章进行投票,如果该文章的发布时间比截止时间小,则已过期,不能进行投票
        if (jedis.zscore("time:", article) < cutoff){
            return;
        }
       //获取文章主键id
        String articleId = article.substring(article.indexOf(':') + 1); article:1    1
        if (jedis.sadd("voted:" + articleId, userId) == 1) {
            jedis.zincrby("score:info", Constants.VOTE_SCORE, article);//分值加400
            jedis.hincrBy(article, "votes", 1l);//投票数加1
        }
   }
   /**
   * 文章列表查询(分页)
   * @return redis查询结果
   */
   @Override
   public List<Map<String, String>> getArticles(int page, String key) {
        int start = (page - 1) * Constants.ARTICLES_PER_PAGE;
        int end = start + Constants.ARTICLES_PER_PAGE - 1;
        //倒序查询出投票数最高的文章,zset有序集合,分值递减
        Set<String> ids = jedis.zrevrange(key, start, end); 
        List<Map<String,String>> articles = new ArrayList<Map<String,String>>();
        for (String id : ids){
            Map<String,String> articleData = jedis.hgetAll(id);
            articleData.put("id", id);
            articles.add(articleData);
       }
       return articles;
   } 
   @Override
   public String hget(String key, String feild) {
      return jedis.hget(key,feild);
   }
   @Override
   public Map<String, String> hgetAll(String key) {
      return jedis.hgetAll(key);
   }
}

Redis业务测试用例代码:

/**
* Redis业务测试用例
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestRedisArticle {
   @Resource(name = "redisArticleServiceImpl")
   private RedisArticleService redisArticleService;
   /**
   * 测试用例:用户发布文章
   */
   @Test
   pub
很抱歉,我无法回答关于图灵课堂诸葛老师的redis实战笔记的问题。因为在提供的引用内容中,并没有提到图灵课堂诸葛老师的redis实战笔记。请提供更多相关信息,我将尽力帮助您。 #### 引用[.reference_title] - *1* [Redis主从,哨兵架构简单搭建](https://blog.csdn.net/weixin_38192427/article/details/120577106)[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^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [B站最全Redis教程全集(2021最新版)(图灵学院诸葛)学习笔记一--五种数据结构与应用场景](https://blog.csdn.net/qq_31135607/article/details/117852917)[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^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [图灵最强诸葛老师最新分享:分布式服务框架原理与实践.pdf篇](https://blog.csdn.net/m0_67322837/article/details/123924158)[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^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值