Redis实战-初识Redis

1 redis简介

redis是一种非关系型数据库。

  • 使用内存存储。
  • 具有:字符串、列表、集合、散列表和有序集合五种存储类型。

附加特性:支持持久化。
实现了主从复制:执行复制的从服务器连上主服务器,接受主服务器发送的整个数据库的初始副本;之后主服务器执行写命令,都会被发给从服务器去执行。

2 redis数据结构简介

Redis可以存储五种类型数据结构:STRING,LIST,SET,HASH和ZSET

数据结构说明如下:

表1 redis提供的五种结构
结构类型结构存储的值结构的读写能力
STRING可以是字符串、整数和浮点数对字符串整个或者一部分执行操作,对整数和浮点数执行自增或自减操作
LIST一个链表,每个节点包含一个字符串从链表两端推入或者弹出元素,读取多个元素等
SET包含字符串的无序集合,不能重复添加、获取、移除,判断是否存在等操作
HASH包含键值对的无序散列表添加、获取、移除键值对,获取所有键值对
ZSET字符串成员,与浮点数之间的映射,排序按照分值添加、删除、获取;根据分值范围获取

2.1 redis中的字符串

字符串基本命令

表2 字符串命令
命令行为
GET获取给定键的值
SET设置给定键的值
DEL删除给定键的值

测试执行结果:
在这里插入图片描述

2.2 redis的列表

redis列表的基本命令如下:

表3 列表命令
命令行为
RPUSH将给定值推到列表的右端
LRANGE获取列表给定范围的值
LINDEX获取列表在给定位置的单个元素
LPOP从列表的左侧弹出一个值

测试执行结果:
在这里插入图片描述

2.3 redis的集合

redis集合基本命令

表3 集合命令
命令行为
SADD将给定元素追加到集合
SMEMBERS返回集合包含的所有元素
SISMEMBER检查给定元素是否存在于集合中
SREM如果给定元素存在于集合中,那么移除这个元素

测试结果:
在这里插入图片描述

2.4 redis的散列

散列基本命令

表4 散列命令
命令行为
HSET在散列里面关联给定的键值对
HGET获取指定散列的键的值
HGETALL获取散列包含的所有键值对
HDEL移除存在的散列

测试结果:
在这里插入图片描述

2.5 redis的有序集合

有序集合的基本命令

表4 有序集合命令
命令行为
ZADD将一个带有分数的成员添加到有序集合
ZRANGE获取多个元素
ZRANGEBYSCORE根据分数获取多个元素
ZREM如果成员存在,则移除

测试结果:
在这里插入图片描述

3 redis示例-文章投票

3.1 数据结构划分

数据结构分析:

  • 书籍信息:包含多个键值对,使用hash进行存储,名称为:article: + 一个时间戳
  • 由于需要进行文章的投票和排名:需要使用两个有序集合:
  •   1 记录文章发布时间,名称为:time
  •   2 记录文章投票得分,名称为:score
  • 为了防止一个用户对一篇文章多次投票,需要针对每一个文章设置黑名单集合,名称为:voted+文章id

3.2 搭建java环境

具体步骤如下:

  1. 新疆springboot项目

  2. 配置redis信息:
    在这里插入图片描述

  3. 配置redis连接和序列化fastjson信息

public class ObjectRedisTemplate extends RedisTemplate<String, Object> {

    public ObjectRedisTemplate() {
        setKeySerializer(RedisSerializer.string());
        setValueSerializer(new GenericFastJsonRedisSerializer());
        setHashKeySerializer(RedisSerializer.string());
        setHashValueSerializer(new GenericFastJsonRedisSerializer());
    }

    public ObjectRedisTemplate(RedisConnectionFactory connectionFactory) {
        this();
        setConnectionFactory(connectionFactory);
        afterPropertiesSet();
    }

    @Override
    protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
        return new DefaultStringRedisConnection(connection);
    }
}
@Configuration
public class RedisConfig {
    @Bean
    public ObjectRedisTemplate objectRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new ObjectRedisTemplate(redisConnectionFactory);
    }
}
  1. 修改redis配置信息redis.conf
    -主要是两处:protected-mode yes 改为:protected-mode no;注释掉环回地址#bin 127.0.0.1

3.3 编写测试demo

定义实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Article {
    private String title;
    private String url;
    private String user;
    private double time;
    private double votes;
}

定义服务包括:投递文章、投票文章和获取所有当前文章

服务类

@Service
public class ArticleService {
    /**
     * 投票截至时间
     */
    private static Integer ONE_WEEK_IN_MILLSECONDS = 7 * 86400000;

    /**
     * 投票对应分数
     */
    private static Integer VOTE_SCORE = 432;

    /**
     * 文章id原子类
     */
    private final AtomicLong atomicId = new AtomicLong(System.currentTimeMillis());

    @Autowired
    ObjectRedisTemplate objectRedisTemplate;

    /**
     * 对文章进行投票
     * @param username 用户名称
     * @param article 文章id
     * @return 是否成功
     */
    public Boolean articleVote(String username, String article) {
        Double time = objectRedisTemplate.opsForZSet().score("time", article);
        if (time == null) {
            return false;
        }
        double v = System.currentTimeMillis() - time;
        if (v > ONE_WEEK_IN_MILLSECONDS) {
            return false;
        }
        Long add = objectRedisTemplate.opsForSet().add("voted"+article, username);
        if (add == null || add == 0) {
            return false;
        }
        objectRedisTemplate.opsForZSet().incrementScore("score", article, VOTE_SCORE);
        return true;
    }

    /**
     * 投递文章
     * @param user 用户名
     * @param title 文章title
     * @param link 文章链接url
     * @return 文章id
     */
    public String postArticle(String user, String title, String link) {
        Map<String, String> map = new HashMap<>();
        map.put("title", title);
        map.put("poster", user);
        map.put("link", link);
        String articleId = "article:" + atomicId.getAndIncrement();
        objectRedisTemplate.opsForHash().putAll(articleId, map);
        if (Boolean.FALSE.equals(objectRedisTemplate.opsForZSet().add("time", articleId, System.currentTimeMillis()))) {
            return "";
        }
        if (Boolean.FALSE.equals(objectRedisTemplate.opsForZSet().add("score", articleId, 0.0))) {
            return "";
        }
        return articleId;
    }

    /**
     * 返回所有文章信息
     * @return 文章列表
     */
    public List<Article> getArticle() {
        Set<Object> articleId = objectRedisTemplate.opsForZSet().range("time", 0, -1);
        List<Article> list = new ArrayList<>();
        for (Object o : articleId) {
            Map<Object, Object> entries = objectRedisTemplate.opsForHash().entries((String) o);
            Double time = objectRedisTemplate.opsForZSet().score("time", o);
            Double score = objectRedisTemplate.opsForZSet().score("score", o);
            Article build = Article.builder().title((String) entries.get("title")).url((String) entries.get("poster")).user((String) entries.get("link")).time(time).votes(score).build();
            list.add(build);
        }
        return list;
    }
}

Controller类

@RestController
public class ArticleController {
    @Autowired
    ArticleService articleService;


    @RequestMapping("/vote")
    public boolean vote(@RequestBody User user) {
        return articleService.articleVote(user.getName(), user.getArticle());
    }

    @RequestMapping("/poster")
    public String poster(@RequestBody Article article) {
        return articleService.postArticle(article.getUser(), article.getTitle(), article.getUrl());
    }

    @RequestMapping("/getposter")
    public List<Article> getPoster() {
        return articleService.getArticle();
    }
    
}

这里的articleId使用原子变量类来保证线程安全。这里的服务根据之前描述的数据结构进行了时机编码。

测试结果(postman):

  1. 模拟投稿
    在这里插入图片描述

  2. 模拟投票
    在这里插入图片描述

  3. 获取所有文章
    在这里插入图片描述

参考文献

[1]《Redis实战》.
[2] Java项目连接远程redis.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LamaxiyaFc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值