简而言之,redis就是以key-value形式存储数据的非关系型数据库
redis的定位是缓存,提高数据读写速度,减轻对数据库的存储与访问压力
redis具有以下优点:
redis具有以下缺点:
redis 中所有命令操作都大致如下 :
类型命令 key 参数数据
Map
存入键值对时,如果key值相同时,后者覆盖前者
可以用于计数器等场景
hash类型结构大致如下 :
在实际开发中, hash 类型用的很少,一般不建议使用
list类型是类似于双向链表的结构,既可以作为栈,又可以作为队列
Map
可以用于一个用户收藏了什么文章的类似场景
String类型的 , 无序的 集合
适用于去重 , 或者抽奖之类的应用场景
总结 :
设计key和value的原则:保证 :唯一性,可读性,灵活性,时效性
redis缓存是暂时将数据保存在内存中的,但是有时候数据会需要持久化,这需要将内存中的数据同步到硬盘来保证数据的持久化,而 Redis 进行持久化有两种方式:
RDB方式 :
可以通过配置,使 redis 在n秒内,如果超过指定数量的key被修改了,就自动同步
但是这种方式存在缺点,因为有时间间隔,如果在间隔内出现意外,数据就会丢失
AOF方式 :
append-only file 的缩写
使用这种方式,redis会将所有收到的命令,用类似于MySQL中的SQL语句一样的形式,写在文件中,当redis再启动时,再读取这些命令,将数据写回内存中
启动 aop 持久化有三种方式:
使用jedis之前先导入相关依赖:
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
dependency>
注意在 redis 中的命令,就是 jedis 中的方法,两者长得一模一样
@Test
public void testJedis(){
// 1:创建Jedis连接池,告诉端口在哪
JedisPool pool = new JedisPool("localhost", 6379);
// 2:从连接池中获取Jedis对象
Jedis jedis = pool.getResource();
// 3:我们只需要操作这里就行
// 4:关闭资源
jedis.close();
pool.destroy();
}
其中,1,2,4 步是固定的,只需要去操作第三步就行,比如:
//存入一个键值对
jedis.set("no1", "66");
//删除一个键值对
jedis.del("no1");
....
继承SpringBoot,以SpringBootTemplate 的方式使用
导入相关依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
修改配置文件:
#application.properties
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=admin #根据情况配置
使用 SpringBootTemplate 操作 redis , 相关的类是:RedisTemplate
但是因为一些公司规定,key-value都使用string类型,所以 上面那个类等价于:StringRedisTemplate
在调用的方法上来说,一般用 StringRedisTemplate 调用的方法和jedis有所区别,很多都是名称补全的
调用不同类型的方法的对象如下:
template.opsForValue().xxx(); //操作字符串
template.opsForHash().xxx(); //操作hash类型
template.opsForList().xxx(); //操作list类型
template.opsForSet().xxx(); //操作set类型
template.opsForZSet().xxx(); //操作Zset类型
对于一些 redis 的全局命令而言,直接就是 template 的方法
//删除所有键值对
Set<String> keys = template.keys("*");
template.delete(keys);
//查询 xx 过期时间
template.getExpire("xx");
//是否存在某个键
template.hasKey("xx");
//取消某个键过期时间
template.persist("xx");
项目中操作涉及到缓存操作,首选redis,但是不是唯一可选的,还有 memcache
有些公司会约定:所有的redis的key跟value都使用字符串(排除使用zeset场景)
redis事务的执行不是原子性的(所以其实就是不支持事务,没意思~)
默认缓存大小为100M,所以当缓存在快要达到100m时,就会触发redis的内存淘汰机制
实战小项目:
需求 :模拟显示一篇文章的访问量 :
思路:
业务层:
@Autowired
private StringRedisTemplate template;
// 拿到 id 之后,给对应id的文章的阅读数量,加一,然后将阅读数返回
@Override
public int CountRead(String id) {
//因为我们的key设计,需要考虑到可读性,此处一个id,让人摸不着头脑
//增强其可读性,做到见名知义
String key = "articleId:" + id;
// 找到数据库中 key 对应的value,将其递增1,返回value值,是Long类型
Long totalRead = template.opsForValue().increment(key);
// Long类型转化为 int 类型并返回
return totalRead.intValue();
}
控制层:
@RestController
@RequestMapping("read")
public class ReadController {
@Autowired
private IReadService readService;
@PostMapping("/countAdd")
public Object countAdd(String id){
//在这里调用业务方法,完成阅读数+1
//拿到返回的阅读数,返回给前端
int totalRead = readService.CountRead(id);
return totalRead;
}
}
前端页面:
<script>
// 页面加载完毕执行
$(function () {
// 发送异步请求,参数为文章的 id , 模拟写一个假id上来
$.post("/read/countAdd",{id:666},function (data) {
// 回调函数data就是文章的阅读数,就是存在 redis 中的key-value的value值
// 将这个value值赋值给对应标签
$("#totalRead").html(data);
})
}script>
Redis 缓存 : 数据存在内存中,其“缓存”的性质,远远大于其“数据存储”的性质,其数据的增删改查也只是像变量操作一样简单
MongoDB 数据库 :存储数据的系统,增删改查可以添加很多条件,就像SQL数据库一样很灵活
两者都是非关系型数据库–NoSQL,采用结构型数据存储,主要区别在于:
内存管理:
数据结构:
数据量和性能:
当物理内存够用的时候,性能:redis>MongoDB>mysql
数据量:mysql>mongodb>redis
可靠性:
因此MongoDB的可靠性优于redis
两者各自的应用场景:
在说应用场景之前先说一个概念 :
TPS : Transactions Per Second : 每秒传输的事务处理个数 ,即服务器每秒处理的事务数;TPS 包括一条消息入和一条消息出,加上一次用户数据库访问
场景一:项目要求 TPS 特别高的,比如微博点赞数,触发频率很高,并发量很大 : 使用 redis
场景二:项目中设计评论的内容,且这个评论表的数据后期会很大,而且还会要求在这个庞大数据量的情况下进行复杂的查询:使用 MongoDB
场景三:推送,评论,用MongoDB,目前是百万级数据,以后是千万级,亿级
ongoDB 采用binlog的方式,支持持久化,增加可靠性
因此MongoDB的可靠性优于redis
两者各自的应用场景:
在说应用场景之前先说一个概念 :
TPS : Transactions Per Second : 每秒传输的事务处理个数 ,即服务器每秒处理的事务数;TPS 包括一条消息入和一条消息出,加上一次用户数据库访问
场景一:项目要求 TPS 特别高的,比如微博点赞数,触发频率很高,并发量很大 : 使用 redis
场景二:项目中设计评论的内容,且这个评论表的数据后期会很大,而且还会要求在这个庞大数据量的情况下进行复杂的查询:使用 MongoDB
场景三:推送,评论,用MongoDB,目前是百万级数据,以后是千万级,亿级
场景四:直播弹幕等用redis,用来存储一些热数据,量不大但是操作频繁