背景介绍
什么是NoSql?
非关系型数据库.
什么是关系型数据库?
根据关系模型创建的数据库.
什么是关系模型?
二维表格模型.有"一对一","一对多"和"多对多"等关系模型.
有哪些类型的非关系型数据库?
- 列模型.应用场景:分布式的文件系统.实例:HBase
- 键值对模型:应用场景:缓存.实例:Redis
- 文档型数据库:应用场景:web应用(与键值对模型类似,value是结构化的数据).实例:MongoDb
- 图形数据库:应用场景:社交网络/推荐系统.实例:略

NoSQL有什么特点?
- 性能好.(存储在内存中)
- 基于键值对,数据之间没有耦合,容易水平拓展.
什么是水平拓展?
提升服务器的数量.
什么是垂直拓展?
提高单机的处理能力.例如:增强硬件性能.提升单机架构性能(无锁结构/缓存/异步)
传统RDBMS(数据库管理软件)和NoSQL有什么区别?
- 非关系型数据库:性能好/易水平拓展
- 关系型数据库:支持复杂查询/支持事务
怎么安装Redis?
[redis安装和启动.md](file:///D:/mynote/软件安装/redis安装和启动.md)
怎么设置Redis后台启动?
daemonize yes
怎么关闭Redis服务?
SHUTDOWN
redis-benchmark有哪些命令?

怎么使用redis-benchmark?
./redis-benchmark -h localhost -p 6379 -c 100 -n 100000
如何分析redis-beenchmark的结果?
[root@www bin]# ./redis-benchmark -p 6379 -h 127.0.0.1 -c 50 -n 5000
====== PING_INLINE ======
5000 requests completed in 0.10 seconds
50 parallel clients
3 bytes payload
keep alive: 1
88.32% <= 1 milliseconds
98.60% <= 2 milliseconds
99.68% <= 3 milliseconds
100.00% <= 3 milliseconds
48076.92 requests per second
====== PING_BULK ======
5000 requests completed in 0.08 seconds
50 parallel clients
3 bytes payload
keep alive: 1
99.02% <= 1 milliseconds
99.48% <= 2 milliseconds
100.00% <= 2 milliseconds
60975.61 requests per second
====== SET ======
5000 requests completed in 0.08 seconds # 5000个请求进行测试
50 parallel clients # 50个并发客户端
3 bytes payload # 每次设置3个字节
keep alive: 1 # 只有一台服务器来处理这些请求
98.88% <= 1 milliseconds
99.32% <= 2 milliseconds
100.00% <= 2 milliseconds # 所有的请求在2毫秒内处理完成
60240.96 requests per second # 每秒可以处理60240.96个请求
基础知识
redis有多少个数据库?
databases 16
怎么切换数据库?
select 3
怎么清空当前数据库?
FLUSHDB
怎么清空所有数据库?
FLASHALL
redis是单线程还是多线程?
单线程
Redis为什么使用单线程?
因为单线程更快.虽然CPU的速度比内存快,但是CPU切换上下文的时间比较长,综合下来,操作内存数据使用单线程更快.(如果是操作硬盘上的数据可以使用多线程,因为硬盘虽然IOPS(每秒输入输出速度)低,但是吞吐量高.可以将多个读写请求一次处理(寻址-读取-写入)来提高速度.) 参考:为什么redis 是单线程的?
什么是redis-key?
怎么删除key?
del k1
怎么设置过期时间?
set k1 v1 ex 20
怎么查看过期剩余时间?
ttl k1
怎么查看key的类型?
type k1
怎么查看一个key是否存在?
exists k1
怎么往key的内容中追加内容
append k1 hehe
怎么获取字符串的长度?
STRLEN k1
怎么给值加1?
incr k1
怎么给值减1?
decr k2
怎么在增减的时候设置步长?
decrby k2 2
怎么获取部分字符串?
getrange k1 0 3
怎么替换部分字符串?
setrange k1 hhhh
怎么设置:如果存在某个key,那么设置这个key,并设置它的过期时间?
setex k1 50 kkkkkk.注意:先是过期时间,后面才是value.
怎么设置:如果不存在某个key,那么设置这个key的值为xxx?
setnx k1 kkk
怎么一次设置多个key-value?
mset k3 v3 k4 v4 k5 v5
怎么一次获取多个key-value?
mget k1 k2 k3 k4 k5
怎么get之前的key-value,然后set新的value?
getset k1 aaaa
怎么往list里添加元素?
lpush list l1 l2 l3 l4 l5rpush list l5 l6 l7
redis的命令区分大小写吗?
命令不区分大小写,变量区分大小写
怎么获取list中的元素?
lrange list 0 -1
怎么移除list中的value?
lpop listrpop list
怎么获取list中指定下标的value?
lindex list 3
怎么获取list中元素的个数?
llen list
怎么移除list中指定个数的值?
lrem list 5 l1.因为list中可以有重复元素,所以可以删除指定个数的某个值的元素.
怎么保留list中指定下标范围的元素并删除其他的元素?
ltrim list 0 3.注意:是保留指定下标的元素而删除其他的元素.
怎么将list中最右边的元素移除并放到另外一个list的最左边?
rpoplpush list
怎么设置list中指定下标的元素的值?
lset list 3 hehe
怎么在指定元素的前面或者后面插入值?
linsert list before l8 l8.5linsert list after l5 l4.5
如果移除了所有的值,list还存在吗?
不存在
set集合有什么特点?
无序不重复.
怎么往set集合中添加元素?
sadd set s1 s2 s3
怎么查看set集合中全部元素?
smembers set
怎么判断set集合中是否存在某个元素?
sismember set s2
怎么获取set集合中元素个数?
scard set
怎么删除set集合中的某个元素?
srem set s1
怎么随机获取set集合中的元素?
srandmenber set 3
怎么随机删除set集合中的元素?
spop set.注意:别看spop里面有pop,实际是随机删除的.
怎么将set集合中指定一个元素移动到另外一个set集合中?
smove set set2 s1
怎么查看两个set集合的差集?
怎么查看两个set集合的差集?
sdiff set set2.会列出所有set中有而set2中没有的元素.
怎么查看两个set集合的交集?
sinter set set2
怎么获取两个set集合的并集?
sunion set set2
什么是hash?
hash是一个map集合.key-map的形式.
怎么添加hash?
hset person age 30
怎么获得hash?
hget person age
怎么获取hash中所有的值?
hgetall person
怎么删除hash中的某个值?
hdel person age
怎么获取hash中的key-value个数?
hlen person
怎么获取hash中指定字段是否存在?
hexists person name
怎么获取hash中所有的key?
hkeys person
怎么获取hash中所有的value?
hvals person
怎么让hash中指定的value自增?
hincrby person age 2
怎么设置hash的map的key不存在的时候添加元素?
hsetnx person phone 189
什么是zset?
有序集合.
怎么添加zset元素?
zadd myzset 9 rabbit.注意:分在元素的前面.
怎么查看所有zset元素?
zrange myzset 0 -1.默认是按照score从小到大排列.
怎么查看zset给定score范围的元素?
zrangebyscore myzset 1000 10000.-inf表示负无穷大,+inf表示正无穷大
zrange和zrangebyscore的区别是什么?
两者共同点都是获取一定范围的zset元素.但是zrange是根据元素的下标的范围来获取的,而zrangebyscore是根据score的范围来获取元素的.
zset怎么根据key删除某个元素?
zrem myzset rabbit
zset怎么降序排列?
zrevrange myzset 0 -1
zset是按照score降序还是升序排列?
升序排列
怎么获取zset集合中的元素个数?
zcount myzset -inf +inf
怎么获取某个score区间范围内的元素个数?
zcount myzset 100 1000
什么是geospatial?
地理位置
怎么添加地理数据?
geoadd city 116.4 39.9 beijing.geospatial类似于key-set.添加的时候,地名在最后.
怎么获取一个地点的经纬度?
geopos city shanghai
怎么查询两地之间的距离?
geodist city beijing shanghai km.查询距离的时候需要指定距离单位,km/m等.
怎么以一个地方(经纬度)为中心,找到给定范围内的地点?
georadius city 110.8 35.5 1000 km
怎么在以一个地方(经纬度)为中心,查找给定范围给定数量的地点?
georadius city 117 33 100 km count 1
怎么以一个给定地方(地名)为中心,查找该地方给定范围内的地点?
georadiusbymember city shanghai 1000 km
GEORADIUSBYMEMBER和GEORADIUS有什么区别?
georadiusbymember是根据地点来查找范围内的地点,而georadius是根据经纬度来查找范围内的地点.
怎么将地方转换为hash值?
geohash city beijing shanghai
GEO的底层是基于什么实现的?
zset.可以用zset的命令来操作geospatial.
什么是Hyperloglog?
基数.
什么是基数?
一个集合中不同值的数目.
使用Hyperloglog有什么优势?
占用的内存固定.2^64个不同元素的计数,只需要12KB内存.
使用Hyperloglog有什么劣势?
会有误差.
怎么往hyperloglog里添加元素?
pfadd mykey a b c d a c e
怎么计算hyperloglog中元素的个数?
pfcount mykey
怎么合并两个hyperloglog中的元素?
pfmerge mykey3 mykey mykey2
什么是Bitmaps?
位图.操作二进制进行存储,只有0和1两个状态.
怎么在bitmap中添加元素?
setbit week 0 1
怎么查看bitmap中的某个元素?
getbit week 1
怎么统计bitmap中的记录?
bitcount week
什么是事务ACID?
- 原子性:要么都执行,要么都不执行.
- 一致性:数据库的数据完整一致.
- 隔离性:并发中事务相互隔离,互不影响
- 持久性:事务提交后数据状态的改变是永久的 参考链接:面试题思考: 什么是事务(ACID)?
Redis有没有原子性?
不能保证原子性.队列中的命令执行时如果出错,那么该条命令不执行,其他命令正常执行.
Redis有没有隔离性?
有.事务中的命令执行的过程不会被其他客户端打断
Redis事务的本质是什么?
在一个队列中一次性/顺序性/排他性的执行一系列命令.
Redis事务有没有隔离级别?
没有隔离级别.在事务提交前命令不会被实际执行.
redis的事务有哪些阶段?
- 开启事务(multi)
- 命令入队
- 执行事务(exec)
怎么开启redis事务?
multi命令
怎么放弃事务?
discard命令
执行事务的时候出现编译型异常(命令写的不对)会怎么样?
该事务中所有的命令都不会被执行
执行事务时出现运行时异常(命令执行时出错)会怎么样?
该条命令报错,其他命令正常执行.
什么是悲观锁?
认为别人会去修改数据,因此每次想修改数据的时候都会上锁,不让别人改动.
什么是乐观锁?
认为别人不会修改数据,因此修改数据的时候不会上锁,但是会判断在此期间有没有人更改数据.
redis的watch类似于什么锁机制?
类似于乐观锁.在修改数据的时候会判断数据是否被修改,如果被修改,那么丢去所有的命令序列.
redis怎么进行监视?
watch money
事务执行失败之后如何再次进行监视?
- 先解锁:
unwatch- 再次监视:
watch money
redis怎么执行乐观锁?
监视锁的值是否发生了变化,如果发生过变化,执行失败.
什么是jedis?
redis官方推荐的java客户端开发包
怎么使用jedis?
- 引入maven依赖
<!-- jedis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
- 创建jedis对象.
Jedis jedis = new Jedis("127.0.0.1",6379);- 使用jedis对象来操作redis,与redis原生命令相似.
jedis有哪些常用API?
参考redis API
springboot怎么集成redis?
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置连接
spring:
redis:
host: 127.0.0.1
port: 6379
- 测试
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testRedis(){
redisTemplate.opsForValue().set("age","30");
redisTemplate.opsForValue().set("addr","南京浦口");
System.out.println(redisTemplate.keys("*"));
}
RedisTemplate和StringRedisTemplate有什么区别?
- RedisTemplate使用的是JdkSerializationRedisSerializer.存入数据会先将数据序列化成字节数组,然后再存.
- StringRedisTemplate使用的是StringRedisSerializer.
- 两者的数据不共通.
什么是lettuce?
生菜.luttuce是springboot 2.x版本之后默认的连接redis server的客户端程序.lettuce基于netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问且线程安全,满足多线程环境下的并发访问,同时它是可伸缩设计,一个连接实例不够的情况下也可以按需增加连接实例.
jedis有什么缺点?
jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连接池,为每个jedis实例增加物理连接.
怎么查看springboot对redis的自动配置?

怎么查看spring的配置文件中redis可以进行哪些配置?
# REDIS (RedisProperties)
spring.redis.cluster.max-redirects= # Maximum number of redirects to follow when executing commands across the cluster.
spring.redis.cluster.nodes= # Comma-separated list of "host:port" pairs to bootstrap from.
spring.redis.database=0 # Database index used by the connection factory.
spring.redis.url= # Connection URL. Overrides host, port, and password. User is ignored. Example: redis://user:password@example.com:6379
spring.redis.host=localhost # Redis server host.
spring.redis.jedis.pool.max-active=8 # Maximum number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
spring.redis.jedis.pool.max-idle=8 # Maximum number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
spring.redis.jedis.pool.max-wait=-1ms # Maximum amount of time a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
spring.redis.jedis.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
spring.redis.lettuce.pool.max-active=8 # Maximum number of connections that can be allocated by the pool at a given time. Use a negative value for no limit.
spring.redis.lettuce.pool.max-idle=8 # Maximum number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
spring.redis.lettuce.pool.max-wait=-1ms # Maximum amount of time a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
spring.redis.lettuce.pool.min-idle=0 # Target for the minimum number of idle connections to maintain in the pool. This setting only has an effect if it is positive.
spring.redis.lettuce.shutdown-timeout=100ms # Shutdown timeout.
spring.redis.password= # Login password of the redis server.
spring.redis.port=6379 # Redis server port.
spring.redis.sentinel.master= # Name of the Redis server.
spring.redis.sentinel.nodes= # Comma-separated list of "host:port" pairs.
spring.redis.ssl=false # Whether to enable SSL support.
spring.redis.timeout= # Connection timeout.
怎么自定义一个key使用String,value使用jackson的redisTemplate?
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
System.out.println("设置redisTemplate的序列化方式>>>>>>>>>>>>>>");
RedisTemplate<String,Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
//Json序列化设置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value采用jackson的方式
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value采用jackson方式序列化
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
为什么序列化的过程中字符串会转义?
因为不同的序列化方式对数据的处理不一样.
怎么让中文字符串不进行转义?
使用
StringRedisSerializer进行序列号
为什么要进行序列化?
数据存储的时候需要设置格式.
redisTemplate怎么设置序列化方式?
template.setKeySerializer(stringRedisSerializer);
redis配置中的include是什么意思?
引入的配置,类似于java中的import
配置中的bind是什么意思?
绑定本机网卡ip地址.
bind 127.0.0.1.通过绑定的网卡ip地址可以访问redis.通过其他网卡则不可以访问.
配置中的protected-mod有什么用?
保护模式. 开启protected-mode后,需要绑定网卡ip或者设置访问密码. 关闭protected-mode后,所有外部网络都可以直接访问
配置中的daemonize有什么用?
- 当设为yes的时候,redis会在后台运行,并将pid号写进redis.conf中pidfile设置的文件中,redis将一直运行,除非手动kill该进程.设为yes必须设置pidfile属性.
- 当设为no的时候,当exit强制退出或者关闭连接工具(putty/xshell)都会导致redis进程退出.
怎么配置redis需要密码才能访问?
requirepass foobared
配置文件中的supervised有什么用?
这个参数是与操作系统有关的.可以通过upstart和systemd管理redis守护进程.
- supervised no - 没有监督互动
- supervised upstart - 通过将Redis置于SIGSTOP模式来启动信号
- supervised systemd - signal systemd将READY = 1写入$ NOTIFY_SOCKET
- supervised auto - 检测upstart或systemd方法基于 UPSTART_JOB或NOTIFY_SOCKET环境变量 参考:redis配置文件详解
配置文件中的pidfile有什么用?
设置pid文件.pid文件是记录进程的id的文件,使用文件锁来避免启动多个线程副本.
配置中loglevel 有什么用?
日志级别
- debug(记录大量日志信息,适用于开发、测试阶段)
- verbose(较多日志信息)
- notice(适量日志信息,使用于生产环境)
- warning(仅有部分重要、关键信息才会被记录)
配置中的logfile有什么用?
日志文件的位置
配置中databases是什么意思?
设置数据库的数量
配置中的save有什么用?
设置存盘时间.格式:
save <间隔时间(秒)> <写入次数>
配置stop-writes-on-bgsave-error是什么意思?
如果用户开启了RDB快照功能,那么redis持久化数据到磁盘时如果出现失败,默认情况下,redis会停止接受所有的写请求.
配置rdbcompression有什么用?
对于存储到磁盘中的快照,设置是否进行压缩存储.压缩存储会消耗cpu,但是节省内存.
配置rdbchecksun有什么用?
存储快照后,设置是否使用CRC64算法来进行数据校验.
配置dir有什么用?
设置快照的存放路径.该路径是一个目录.
怎么设置能连接redis的最大的客户端数量?
maxclients 1000
配置的maxmemory有什么作用?
最大内存容量.配合到达上限后的处理策略使用.
配置maxmemory-policy noeviction有什么作用?
- volatile-lru 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
- allkeys-lru 利用LRU算法移除任何key
- volatile-random 移除设置过过期时间的随机key
- allkeys-random 移除随机key
- volatile-ttl 移除即将过期的key(minor TTL)
- noeviction noeviction 不移除任何key,只是返回一个写错误 ,默认选项
配置appendonly有什么作用?
即AOF(appendonlyfile).redis默认使用rdb方式持久化,但是redis中途宕机可能导致几分钟的数据丢失,append only file是另一种持久化方式,redis每次把写入的数据都写入appendonly.aof文件中.
配置appendfilename有什么作用?
aof文件名
配置appendfsync是什么意思?
aof持久化策略.
- no表示不执行fsync.由操作系统自己同步数据,速度最快.
- always表示每次写入都执行fsync.消耗性能.
- ererysec表示每秒都执行一次fsync.丢失的化最多丢失一秒的数据
redis为什么要持久化?
redis是内存数据库,如果不将内存中的数据保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失.
什么是rdb?
redis database.使用二进制格式保存对数据库的操作的快照.
rdb的原理是什么?
redis会单独创建(fork)一个子进程来进行持久化,先将数据写入临时文件,等持久化过程都结束了再用这个临时文件替换上次持久化好的文件.整个过程,主进程不进行任何IO操作,因此性能极高,缺点是可能丢失最后一次持久化后的数据.
rdb保存的文件是什么?
dump.rdb
保存rdb文件的触发机制是什么?
- save规则满足
- flushall命令
- 退出redis
如何从rdb文件恢复数据?
将rdb文件放在redis启动目录即可.redis启动时会自动检查dump.rdb,恢复其中的数据.
怎么查看需要存放的rdb文件位置?
使用命令
config get dir
rdb的优点和缺点是什么?
- 优点:效率高,适合大规模的数据恢复.
- 缺点:存档之后数据可能丢失
什么是aof?
把所有命令都记录下来.恢复的时候把文件全部执行一遍.
aof文件被破坏了,怎么修复?
使用
redis-check-aof --fix工具进行修复.例如:redis-check-aof --fix appendonly.aof
aof有哪些优点和缺点?
- 优点:可以设置更高频率的同步(因为rdb操作需要fork子进程,因此操作频率不能太高),会提高数据的完整性.
- 缺点:文件较大,修复数据的速度也更慢.
配置auto-aof-rewrite-min-size是什么意思?
设置允许重写的最小aof文件大小.是为了避免达到了约定的百分比,但是文件尺寸还很小的情况下覆盖之前的aof文件.
什么是发布订阅?
是一种消息通信模式.发送者发送消息,订阅者接受消息.
redis怎么订阅和发布?
订阅一个频道:
subscribe guohao发送消息到队列:publish guohao 'hello,i am guohao'
redis发布订阅的原理是什么?
redis-server维护了一个字典,key:channel,value:订阅该频道的客户端组成的链表.当发布者发送小的时候,redis-server根据给定的频道,遍历链表,将消息发送给订阅者.
redis的发布订阅有哪些应用场景?
- 实时消息
- 聊天室
- 订阅/关注系统
复杂的发布-订阅场景使用什么工具实现?
消息中间件MQ.
什么是主从复制?
把一台redis服务器上的数据复制到另外一台.前者称为主节点,后者称为从节点.复制是单向的,只能从主节点复制到从节点.
什么是数据冗余?
数据集合中重复的数据.
数据冗余的优缺点是什么?
- 优点:可用于数据间建立联系/数据恢复/数据核查/减少数据通讯开销(如分布式数据库在不同场地的重复)
- 缺点:浪费空间
主从复制的作用是什么?
- 数据冗余:
- 故障恢复
- 负载均衡
- 高可用(集群)基石
主从模式有哪些优缺点?
- 优点: 1.1 可读写分离,减轻主节点的压力 1.2 主节点挂了不影响从节点读
- 缺点: 2.1 主节点挂了后不支持写操作且不会推举出新的主节点 2.2 难以扩容(每个服务器都是全量的数据,能放多少数据取决于服务器的容量,跟服务器数量没有关系)
怎么设置redis一主二从?
只需配置从机即可. 使用命令配置(只在本次生效):连接两台从机客户端后,使用
slaveof hostip的方式来配置从机.
怎么查看客户端的主从关系?
使用命令
info replication
怎么设置redis服务端为从服务器?
使用
slaveof xxx命令
命令行配置的从机,重启服务后配置会保存吗?
不会
正常的永久的主从配置怎么配置?
使用配置文件配置
主机断开连接再恢复,从机能否连接到主机?
可以.
从机断开连接后再恢复,能否恢复数据?
可以.
从机连接主机后恢复数据的原理是什么?
从机启动成功后连接主机会发出一个sync同步命令,主机接到命令,会开启后台的存盘进程,收集所有的数据修改命令,发送给从机,从机进行数据恢复.
什么是全量复制?
将主节点的所有数据都发送给从节点
什么是增量复制?
主节点将从节点丢失的数据传输给从节点
什么情况下是全量复制什么情况下是增量复制?
- 全量复制: 1.1 从节点首次启动或者重启之后 1.2 从节点没有重启,但是掉线了,而且掉线重连后不满足部分复制的条件
- 增量复制: 2.1 从节点没有重启,只是单纯掉线.从节点保存的run id与master当前的run id一致.主节点保存的offset可用.
什么是层层链路?
每一个服务器既是上一层服务器的从节点,又是下一个服务器的主节点.
如果主机断开了,从机怎么让自己成为主节点?
使用
slaveof no one
什么是哨兵模式?
sentinel.哨兵模式是由一个或者多个sentinel实例组成的系统,可以监视任意的主从服务器,当被监视的主服务器下线时,自动将该主服务器下的某个从服务器升级为新的主服务器.
什么是主观下线?
仅仅一台哨兵认为主服务器不可用.
什么是客观下线?
多个哨兵检测到主服务器不可用,并在投票通过后进行故障转移.然后通过发布订阅模式让各个哨兵把监控的从服务器切换为主服务器.
怎么开启sentinel?
- 配置哨兵模式的配置文件sentinel.conf.
sentinel monitor myredis 127.0.0.1 6379 1.最后的1表示如果主机挂了,投票决定新的主机是谁.- 使用命令启动哨兵模式.
./redis-sentinel ../etc/sentinel.conf来启动哨兵模式.
怎么设置主机挂了,从机投票看谁接替成为主机?
sentinel monitor myredis 127.0.0.1 6379 1
怎么启动哨兵?
./redis-sentinel ../etc/sentinel.conf
如果主机挂了之后重新连回来了,它会是什么角色?
会变成从机
哨兵模式有什么优缺点?
- 优点: 1.1 所有主从复制的有点,它全都有 1.2 是主从模式的升级,从手动到自动,系统更加健壮. 1.3 系统的可用性更高
- 缺点: 2.1 redis不方便在线扩容 2.2 哨兵模式的配置比较复杂
哨兵模式有哪些配置?
sentinel monitor <master-name> <ip> <redis-port> <quorum>
#告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效
sentinel auth-pass <master-name> <password>
#设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。
sentinel down-after-milliseconds <master-name> <milliseconds>
#这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒
sentinel parallel-syncs <master-name> <numslaves>
#这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel failover-timeout <master-name> <milliseconds>
#failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向#master,但是就不按parallel-syncs所配置的规则来了。
什么是redis的缓存穿透?
查询一个不存在的数据,由于缓存是如果数据不存在,就去数据库中去查,那么查询这些不存在的数据,每次都会查询数据库.
怎么解决缓存穿透?
- 布隆过滤器:对一个key进行多次hash,得到多个值,然后将这些值对应的bitmap的对应位置置为1.最后在查询的时候,对key也进行多次hash,如果对应的值的位置都为1,那么该key可能存在,否则,该key一定不存在.参考链接:详解布隆过滤器的原理、使用场景和注意事项
- 缓存空值.如果从数据库查询的结果为空,那么把空值进行缓存,并设置一个过期时间(防止占用太多空间).
什么是缓存击穿?
某一个key过期了,同时并发的用户特别多,都去请求这个key,导致数据库的压力剧增.该类数据一般是热点数据.
怎么解决缓存击穿?
- 设置热点数据永不过期.
- 加互斥锁.使用分布式锁,保证每个key同时只有一个线程去查询,其他的线程等待.这种方式将高并发的压力转移到了分布式锁,对分布式锁的考验很大.
什么是分布式锁?
控制分布式系统有序操作资源,同一时间只有一个客户端能够操作资源.
有哪些分布式锁?
- Memcached分布式锁:利用memcached的
add命令,由于此命令是原子性操作,只有key不存在的时候,才能add成功,也就意味着获得了锁.- redis分布式锁:利用redis的
setnx命令,此命令同样是原子性操作,只有key不存在才能set成功.参考链接:漫画:什么是分布式锁?- zookeeper分布式锁:利用zookeeper的临时顺序节点,来实现分布式锁和等待队列.zookeeper设计初衷就是为了实现分布式锁服务的.参考链接:漫画:如何用Zookeeper实现分布式锁?
- chubby:谷歌实现的粗粒度分布式锁服务,底层利用了paxos一致性算法.
怎么实现分布式锁?
参考:[zookeeper](file:///D:/springbootdemo/spring-boot-demo/spring-boot-demo-zookeeper/src/main/java/com/xkcoding/zookeeper) 参考:redis分布式锁原理及实现
分布式锁有哪些应用场景?
- 分布式系统的定时任务
- 订单防止超卖
怎么解决使用分布式锁的时候,setnx操作和expire操作中间存在时间间隔,导致加锁后如果程序挂了,锁就永远锁住?
redis 2.6.12版本之后为set命令添加了参数,
set(key,1,30,NX),这样加锁和设置过期时间就是原子操作了.
怎么防止线程A执行超时后释放锁,线程B开始执行,然后线程A执行完删除锁的时候把线程B的锁删除?
设置锁的值为线程的id,删除锁的时候进行比对,只删除跟自己线程id相同的锁.
怎么防止线程A执行超时后锁的失效?
获得锁的线程同时开启一个守护线程,在锁过期之前给锁续航.
怎么防止重复提交?
使用分布式锁.
什么是缓存雪崩?
缓存集中过期或者redis服务器故障,发生大量的缓存穿透,对数据库造成巨大的压力.
怎么解决缓存雪崩?
- 搭建redis集群,防止单个节点不可用.
- 缓存失效后通过加锁或者队列来控制数据库写缓存的线程数量.
- 数据预热:在正式部署之前,对可能访问的数据先访问一遍进行缓存,并给数据设置不同的过期时间.
什么是幂等性?
多次执行的效果和执行一次的效果是一样的.查询操作和删除操作天然是幂等的.
怎么实现接口的幂等性?
- 添加唯一索引:新增数据的时候增加一个唯一索引,比如添加资金信息,一个用户只能有一条记录,给用户id字段添加唯一索引,如果数据库新增报错,直接返回结果即可.
- token机制: 2.1 集群环境:采用token+redis
2.2 单JVM环境:采用token+redis或者token+jvm内存- 乐观锁: 3.1 版本号:
update table_xxx set name = #name#,version = version+1 where version = #version#3.2 条件限制:...- 分布式锁:redis分布式锁和zookeeper分布式锁.
- select + insert:只适用于并发不高的系统
- 状态机
- 对外接口需要传入参数:source来源/seq序列号,用source+seq在数据库做唯一索引,防止多次付款.当第三方调用的时候先查询,如果处理过,返回结果,否则处理后返回结果. 参考链接:如何做到接口的幂等性
token机制实现幂等性的原理是什么?
- 数据提交前要申请token.并将此token放入redis里.
- 请求接口的时候,将token放到header里或者作为请求参数请求接口.
- 后台判断redis中是否有此token
- 如果存在此token,正常处理业务逻辑,并从redis中删除此token.(实际上为了应对高并发场景,是直接删除此token,如果删除成功,表明存在此token,正常处理业务,否则表示重复提交,返回相应提示.)