1.redis常见数据结构?
字符串(string):普通字符串,常用
哈希(hash):适合存储对象
列表(list):按照插入顺序排序,可以有重复元素
集合(set):无序集合,没有重复元素
有序集合(sorted set / zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素
2.redis在项目中的使用场景?
redis的key 的数据结构是如何选型的redis的key的规范是如何设计的具体业务是怎么样的如何使用redis解决的业务
Spring Data Redis
1.依赖
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.4.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置application.yml
spring:
#Redis相关配置
redis:
host: localhost
port: 6379
#password: 123456
database: 0 #操作的是0号数据库
jedis:
#Redis连接池配置
pool:
max-active: 8 #最大连接数
max-wait: 1ms #连接池最大阻塞等待时间
max-idle: 4 #连接池中的最大空闲连接
min-idle: 0 #连接池中的最小空闲连接
3.操作字符串类型数据
/**
* 操作String类型数据
*/
@Test
public void testString(){
//存值
redisTemplate.opsForValue().set("city123","beijing");
//取值
String value = (String) redisTemplate.opsForValue().get("city123");
System.out.println(value);
//存值,同时设置过期时间
redisTemplate.opsForValue().set("key1","value1",10l, TimeUnit.SECONDS);
//存值,如果存在则不执行任何操作
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city1234", "nanjing");
System.out.println(aBoolean);
}
4.操作哈希类型数据
/**
* 操作Hash类型数据
*/
@Test
public void testHash(){
HashOperations hashOperations = redisTemplate.opsForHash();
//存值
hashOperations.put("002","name","xiaoming");
hashOperations.put("002","age","20");
hashOperations.put("002","address","bj");
//取值
String age = (String) hashOperations.get("002", "age");
System.out.println(age);
//获得hash结构中的所有字段
Set keys = hashOperations.keys("002");
for (Object key : keys) {
System.out.println(key);
}
//获得hash结构中的所有值
List values = hashOperations.values("002");
for (Object value : values) {
System.out.println(value);
}
}
5.操作列表类型数据
/**
* 操作List类型的数据
*/
@Test
public void testList(){
ListOperations listOperations = redisTemplate.opsForList();
//存值
listOperations.leftPush("mylist","a");
listOperations.leftPushAll("mylist","b","c","d");
//取值
List<String> mylist = listOperations.range("mylist", 0, -1);
for (String value : mylist) {
System.out.println(value);
}
//获得列表长度 llen
Long size = listOperations.size("mylist");
int lSize = size.intValue();
for (int i = 0; i < lSize; i++) {
//出队列
String element = (String) listOperations.rightPop("mylist");
System.out.println(element);
}
}
5.操作集合类型数据
/**
* 操作Set类型的数据
*/
@Test
public void testSet(){
SetOperations setOperations = redisTemplate.opsForSet();
//存值
setOperations.add("myset","a","b","c","a");
//取值
Set<String> myset = setOperations.members("myset");
for (String o : myset) {
System.out.println(o);
}
//删除成员
setOperations.remove("myset","a","b");
//取值
myset = setOperations.members("myset");
for (String o : myset) {
System.out.println(o);
}
}
6.操作有序集合类型数据
/**
* 操作ZSet类型的数据
*/
@Test
public void testZset(){
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
//存值
zSetOperations.add("myZset","a",10.0);
zSetOperations.add("myZset","b",11.0);
zSetOperations.add("myZset","c",12.0);
zSetOperations.add("myZset","a",13.0);
//取值
Set<String> myZset = zSetOperations.range("myZset", 0, -1);
for (String s : myZset) {
System.out.println(s);
}
//修改分数
zSetOperations.incrementScore("myZset","b",20.0);
//取值
myZset = zSetOperations.range("myZset", 0, -1);
for (String s : myZset) {
System.out.println(s);
}
//删除成员
zSetOperations.remove("myZset","a","b");
//取值
myZset = zSetOperations.range("myZset", 0, -1);
for (String s : myZset) {
System.out.println(s);
}
}
7.通用操作
/**
* 通用操作,针对不同的数据类型都可以操作
*/
@Test
public void testCommon(){
//获取Redis中所有的key
Set<String> keys = redisTemplate.keys("*");
for (String key : keys) {
System.out.println(key);
}
//判断某个key是否存在
Boolean itcast = redisTemplate.hasKey("itcast");
System.out.println(itcast);
//删除指定key
redisTemplate.delete("myZset");
//获取指定key对应的value的数据类型
DataType dataType = redisTemplate.type("myset");
System.out.println(dataType.name());
}
4.redis的事务机制的介绍?
Redis对于命令执行错误处理,有两种解决方式:
- 语法错误(编译)
- 执行错误(运行)
语法错误:执行命令的语法不正确。
此时整个事务队列中,存在一条正确指令,两条语法错误指令, 当执行exec后,会直接返回错误,正确的命令也不会执行。和我们正常理解的事务概念相同。
执行错误:命令在运行过程中出现错误。
通过上面事务执行可以看到,语法本身是没有问题的,所以运行之前redis无法发现错误,但是在执行时出现了错误,因此只会错误的命令不执行, 而正确的命令仍然能够正常执行。
5.redis的持久化机制?
1.RDB快照
RDB(Redis DataBase)是Redis默认存储方式。其基于快照思想,当符合一定条件(手动或自动触发)时,Redis会将这一刻的内存数据进行快照并保存在磁盘上,产生一个经过压缩的二进制文件,文件后缀名.rdb。
优点:
- 基于二进制文件完成数据备份,占用空间少,便于文件传输。
- 能够自定义规则,根据Redis繁忙状态进行数据备份。
缺点:
- 无法保证数据完整性,会丢失最后一次快照后的所有数据。
- bgsave执行每次执行都会阻塞Redis服务进程创建子线程,频繁执行影响系统吞吐率。
2.AOF
AOF(append only file)是Redis提供了另外一种持久化机制。与RDB记录数据不同,当开启AOF持久化后,Redis会将客户端发送的所有更改数据的命令,记录到磁盘中的AOF文件。 这样的话,当Redis重启后,通过读取AOF文件,按顺序获取到记录的数据修改命令,即可完成数据恢复。
| 模式 | aof_buf写入到AOF是否阻塞 | AOF文件写入磁盘是否阻塞 | 宕机重启时丢失的数据量 | 效率 | 安全 |
|---|---|---|---|---|---|
| always | 阻塞 | 阻塞 | 最多只丢失一个命令的数据 | 低 | 高 |
| everysec | 阻塞 | 不阻塞 | 不超过两秒的数据 | 中 | 中 |
| no | 阻塞 | 阻塞 | 操作系统最后一次对AOF写入磁盘的数据 | 高 | 低 |
6.RDB和AOF持久化的区别?
- RDB默认开启,AOF需手动开启。
- RDB性能优于AOF。
- AOF安全性优于RDB。
- AOF优先级高于RDB。
- RDB存储某个时刻的数据快照,AOF存储写命令。
- RDB在配置触发状态会丢失最后一次快照以后更改的所有数据,AOF默认使用everysec,每秒保存一次,最多丢失两秒以内的数据。
7.redis高可用(集群策略)?
主从复制
* 读写分离:**主写从读**,提高服务器的读写负载能力
* 负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量
* 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复
* 数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式
* 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案
哨兵模式
* 主从集群间可以实现自动切换,可用性更高
* 数据更大限度的防止丢失
* 解决哨兵的集群高可用问题,减少误判率
分片集群
为了解决单机Redis容量有限的问题,将数据按一定的规则分配到多台机器,内存/QPS不受限于单机,提高并发量。
8.redis key的过期淘汰策略?
- 定时删除
- 惰性删除
- 定期删除
9.redis 内存淘汰策略?
在Redis中默认提供了三类八种淘汰策略。
10.redis缓存穿透的问题?
11.redis缓存击穿的问题?
12.redis缓存雪崩的问题?
13.redis实现分布式锁的原理?
