国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Redis實戰(zhàn)SpringBoot版本之投票服務(wù)

fuyi501 / 2790人閱讀

摘要:序?qū)崙?zhàn)是本好東東,值得詳細研讀。本文主要是對第一章的投票服務(wù)的代碼從改為的版本。

redis實戰(zhàn)是本好東東,值得詳細研讀。本文主要是對第一章的投票服務(wù)的代碼從jredis改為SpringBoot的redis template版本。

功能說明

用redis來存儲文章

對文章投票

每個用戶只能投一次

文章按投票和時間排行

文章打標(biāo)簽

數(shù)據(jù)結(jié)構(gòu)選擇

文章采用hash存儲

用redis的incr來實現(xiàn)文章的自增id

用set來記錄每篇文章已投票的用戶

用zset存儲文章與得分,創(chuàng)建時間

用set來存儲標(biāo)簽里有哪些文章

常量聲明
/**
     * incr,獲取文章的id
     */
    public static final String KEY_ARTICLE_ID_SEQ = "articleIdSeq";

    /**
     * 數(shù)據(jù)結(jié)構(gòu):SET
     * key -- voted:articleId
     * value -- user
     * 記錄每篇文章的投票用戶
     */
    public static final String KEY_VOTE_ARTICLE_PREFIX = "votedSet:";

    /**
     * 數(shù)據(jù)結(jié)構(gòu):map
     * key -- articleMap:id
     * value --  article map
     */
    public static final String KEY_ARTICLE_PREFIX = "articleMap:";

    /**
     * 數(shù)據(jù)結(jié)構(gòu):zset
     * key -- scoreZSet
     * value -- 得分 articleMap:id
     */
    public static final String KEY_SCORE = "scoreZSet";

    /**
     * 數(shù)據(jù)結(jié)構(gòu):zset
     * key -- timeZSet
     * value -- 得分 articleMap:id
     */
    public static final String KEY_TIME = "timeZSet";

    /**
     * 文章標(biāo)簽前綴
     * 數(shù)據(jù)結(jié)構(gòu) set
     * key -- tagSet:tag
     * value -- articleMap:id
     */
    public static final String KEY_TAG_PREFIX = "tagSet:";

    /**
     * 文章用戶投票記錄的過期時間
     */
    public static final int ARTICLE_USER_VOTE_EXPIRE_DAY = 7;

    /**
     * 文章用戶投票記錄的過期時間
     * 秒為單位
     */
    public static final int ONE_WEEK_IN_SECONDS = 7 * 86400;

    /**
     * 投票得分
     */
    public static final int VOTE_SCORE = 432;

    /**
     * 每頁多少條記錄
     */
    public static final int ARTICLES_PER_PAGE = 25;
主要功能 添加文章
/**
     * 添加文章
     * @param user
     * @param title
     * @param link
     * @return 文章的自增id
     */
    public Long postArticle(String user,String title,String link){
        ValueOperations intOps = redisTemplate.opsForValue();
        Long id = intOps.increment(KEY_ARTICLE_ID_SEQ,1L);

        //本人發(fā)布的文章,自動添加到已投票set中
        voteInternal(id,user);

        Map articleData = new HashMap();
        articleData.put("title", title);
        articleData.put("link", link);
        articleData.put("user", user);
        long nowInSecs = System.currentTimeMillis() / 1000;
        articleData.put("now", String.valueOf(nowInSecs));
        articleData.put("votes", "1"); //主要投票數(shù)的計數(shù)器

        //保存文章
        String articleKey = formArticleKey(id);
        redisTemplate.opsForHash().putAll(articleKey, articleData);

        //記錄得分和時間
        redisTemplate.boundZSetOps(KEY_SCORE).add(articleKey,nowInSecs + VOTE_SCORE);
        redisTemplate.boundZSetOps(KEY_TIME).add(articleKey,nowInSecs);

        return id;
    }
給文章投票
/**
     * 用戶給文章投票
     * 嚴格一點需要加事務(wù)
     * @param user
     * @param id
     */
    public void voteArticle(String user,Long id){
        long now = System.currentTimeMillis() / 1000;
        String articleKey = formArticleKey(id);
        Double score = redisTemplate.boundZSetOps(KEY_SCORE).score(articleKey);
        //文章發(fā)布超過一周,不能投票
        if(score.longValue() + ONE_WEEK_IN_SECONDS < now){
            return;
        }

        //判斷用戶是否可以投票
        //若已經(jīng)投票則返回,未投票則投票,并增加投票記錄
        Long tryVote = voteInternal(id,user);
        if(tryVote == 0){
            return;
        }

        //給文章增加投票
        redisTemplate.opsForHash().increment(articleKey,"votes",1L);
        //增加文章的得分
        redisTemplate.boundZSetOps(KEY_SCORE).incrementScore(articleKey,VOTE_SCORE);
    }
根據(jù)id獲取文章
/**
     * 根據(jù)id獲取文章內(nèi)容
     * @param id
     * @return
     */
    public ArticleBean getArticleById(Long id){
        Map data = redisTemplate.opsForHash().entries(formArticleKey(id));
        ArticleBean bean = new ArticleBean();
        bean.setId(id);
        try {
            BeanUtils.populate(bean,data);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return bean;
    }
給文章打標(biāo)簽
/**
     * 給文章打標(biāo)簽
     * @param id
     * @param tags
     */
    public void tagArticle(Long id,String[] tags){
        String articleKey = formArticleKey(id);
        for(String tag:tags){
            String tagKey = formTagKey(tag);
            redisTemplate.opsForSet().add(tagKey,articleKey);
        }
    }
獲取排行具體實現(xiàn)
/**
     * 根據(jù)排序及頁數(shù)獲取文章
     * @param page
     * @param zrangeKey
     * @return
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private List getArticleRank(int page,String zrangeKey){
        int start = (page - 1) * ARTICLES_PER_PAGE;
        int end = start + ARTICLES_PER_PAGE - 1;

        BoundZSetOperations ops = redisTemplate.boundZSetOps(zrangeKey);
        //根據(jù)得分從大到小
        Set ids = ops.reverseRange(start, end);
        List rs = ids.stream().map(new Function() {
            @Override
            public ArticleBean apply(String id) {
                HashOperations hashOps = redisTemplate.opsForHash();
                Map map = hashOps.entries(id);
                ArticleBean bean = new ArticleBean();
                bean.setId(Long.valueOf(id.substring(id.indexOf(":") + 1)));
                try {
                    BeanUtils.populate(bean, map);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                return bean;
            }
        }).collect(Collectors.toList());
        return rs;
    }
獲取各種排行
/**
     * 根據(jù)標(biāo)簽獲取文章排名
     * @param page
     * @param zrangeKey
     * @param tag
     * @return
     */
    public List getArticleRankByTag(int page,String zrangeKey,String tag){
        String scoreTagKey = formScoreTagKey(zrangeKey, tag);
        Boolean exist = redisTemplate.hasKey(scoreTagKey);
        if(!exist){
            Long rs = redisTemplate.opsForZSet().intersectAndStore(formTagKey(tag),zrangeKey,scoreTagKey);
            if(rs == 1){
                redisTemplate.expire(scoreTagKey,1,TimeUnit.MINUTES);
            }
        }
        return getArticleRank(page,scoreTagKey);
    }

    /**
     * 根據(jù)得分排序
     * @param page
     * @return
     */
    public List getArticleRankByScore(int page){
        return getArticleRank(page,KEY_SCORE);
    }

    /**
     * 根據(jù)時間排序
     * @param page
     * @return
     */
    public List getArticleRankByTime(int page){
        return getArticleRank(page,KEY_TIME);
    }
junit測試
/**
 * Created by codecraft on 2016-02-11.
 */
public class VoteServiceTest extends RedisdemoApplicationTests{

    @Autowired
    VoteService voteService;

    @Autowired
    RedisTemplate redisTemplate;

    @Test
    public void incrMap(){
        //template.setHashValueSerializer(new StringRedisSerializer(StandardCharsets.UTF_8));
        //這里得用string寫進去
        redisTemplate.opsForHash().put("user-abcde", "count", "1");
        redisTemplate.opsForHash().increment("user-abcde", "count", 5);

        //error java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
        redisTemplate.opsForHash().put("user-abcde", "now", System.currentTimeMillis());
        System.out.println(redisTemplate.opsForHash().get("user-abcde", "now"));
    }

    @Test
    public void delete(){
        for(int i=0;i<100;i++){
            voteService.delete(i+1L);
        }
        redisTemplate.delete("articleIdSeq");
    }

    @Test
    public void post() throws InterruptedException {
        for(int i=0;i<100;i++){
            voteService.postArticle("user" + i, "title" + i, "link" + i);
            Thread.sleep(1000);
        }
        for(int i=0;i<100;i++){
            ArticleBean bean  = voteService.getArticleById(i + 1L);
            System.out.println(ToStringBuilder.reflectionToString(bean));
        }
    }

    @Test
    public void vote(){
        Random random = new Random();
        IntStream.range(1,31).forEach(x -> {
            Long articleId = random.nextInt(100) + 1L;
            String user = "user" + (random.nextInt(100) + 1);
            voteService.voteArticle(user,articleId);
        });
    }

    @Test
    public void addTag(){
        Random random = new Random();
        IntStream.range(1,31).forEach(x -> {
            Long articleId = random.nextInt(100) + 1L;
            String tag = "tag" + (random.nextInt(5) + 1);
            voteService.tagArticle(articleId, new String[]{tag});
        });
    }

    @Test
    public void getByScore(){
        List data = voteService.getArticleRankByScore(1);
        data.stream().forEach(System.out::println);
    }

    @Test
    public void getByTime(){
        List data = voteService.getArticleRankByTime(1);
        data.stream().forEach(System.out::println);
    }

    @Test
    public void getByTag(){
        List data = voteService.getArticleRankByTag(1, VoteService.KEY_SCORE,"tag1");
        data.stream().forEach(System.out::println);
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/65864.html

相關(guān)文章

  • 一個網(wǎng)站的微服務(wù)架構(gòu)實戰(zhàn)(2)k8s遷移

    摘要:前言我們一起回顧上一篇文章平臺的微服務(wù)架構(gòu)和,一共通過構(gòu)建了三個鏡像數(shù)據(jù)庫,部署前端頁面的,和接口。最近阿里云產(chǎn)品春節(jié)大促銷,我一時沒忍住又買了一臺服務(wù)器,打完折扣還是很貴。是一個非常穩(wěn)定的,可移植的網(wǎng)絡(luò)文件系統(tǒng)。 前言 我們一起回顧上一篇文章《Bees平臺的微服務(wù)架構(gòu)(1)docker和docker-compose》,一共通過Dockerfile構(gòu)建了三個docker鏡像:mysql...

    Forelax 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<