关系型数据库:
优点:
缺点:
特点:
Nosql分类:键值(Key-Value)存储数据库、列存储数据库、文档型数据库、图形(Graph)数据库。
Redis,Remote Dictionary Server,远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis作用:
官网:https://redis.io/
中文网站:http://www.redis.cn/
Map
应用场景:
Map
应用场景:
Map
应用场景(链表结构,适合作为栈和队列使用):
Map
应用场景:
Map
通过给每个member赋一个score实现排序,其中member唯一,score不唯一。
应用场景:
Geo的底层实现是Zset,可以用Zset命令来操作geo。
应用场景:
基数:不重复的元素。
Hyperloglog用来进行基数统计。
优点:占用的内存是固定的,2^64不同的元素的存储,只需要12KB内存。
缺点:有0.81%错误率。
应用场景:
Redis提供了Bitmaps这个“数据类型”可以实现对位的操作:
应用场景:
Redis事务:一组命令的集合,一个事务中的所有命令都会被序列化,在事务的执行过程中会按照顺序执行。
Redis事务具有一次性、顺序性、排他性。
Redis事务没有隔离级别的概念。
Redis单条命令保证原子性,但是事务不保证原子性。
Redis的事务:
编译型异常:执行事务时报错,所有的命令都不会被执行。
运行时异常:其他命令可以正常执行,错误命令抛出异常。因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
利用watch监视数据是否修改,若数据变化了则整个事务会被取消,实现乐观锁操作。
如果想逻辑性的一起执行多条指令,在执行过程不被别的请求打断,那么Redis提供了Lua脚本,Redis服务器会单线程原子性执行lua脚本,保证了在执行过程中不会被其他请求打断。
优点:
官方推荐的java客户端有Jedis、Lettuce、Redisson。
性能对比:
Jedis的性能比lettuce和Redisson都要差一点,三者的主要差异在于以下:
功能对比:
SpringBoot2.x版本后,其内置的Redis中间件从Jedis换成了lettuce。
#自动配置类 RedisAutoConfiguration
#配置文件 RedisProperties
因为java使用ISO-8859-1编码进行传输数据的,那么传输字符串的话,编解码会不一致,一定会出现乱码,所以需要自己重写一个RedisTemplate来修改默认的序列化方式。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// jackson序列化所有的类
Jackson2JsonRedisSerializer Jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// jackson序列化的一些配置
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance);
Jackson2JsonRedisSerializer.setObjectMapper(om);
// String的序列化
StringRedisSerializer stringSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringSerializer);
//hash的key也采用String的序列化方式
template.setHashKeySerializer(stringSerializer);
//value采用jackson序列化方式
template.setValueSerializer(Jackson2JsonRedisSerializer);
//hash的value也采用jackson序列化方式
template.setHashValueSerializer(Jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
Redis管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。使用管道技术可以大大提高速度性能。
https://blog.csdn.net/sinat_25207295/article/details/117925174
在指定时间间隔内将内存中的数据集快照写入磁盘,恢复时将将快照文件直接读入内存里。Redis单独fork一个子进程来进行持久化,先将数据写入一个临时文件中,待持久化过程都结束之后,用临时文件替换上次持久化好的文件。整个过程中主进程不进行IO操作,确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
默认使用RDB。
触发机制:
优点:
缺点:
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
默认不使用,需要手动设置开启。
优点:
Redis发布订阅(pub/sub)是一种消息通信模式:发布者(pub)发布消息,订阅者(sub)接受消息。Redis客户端可以订阅任意数量的频道。
实现原理:
使用注意:
针对消息订阅发布功能,市面上很多大厂使用的是kafka、RabbitMQ、ActiveMQ, RocketMQ等这几种,redis的订阅发布功能相比而言,相对轻量,针对数据准确和安全性要求没有那么高可以直接使用。
Redis Stream 从概念上来说,就像是一个仅追加内容的消息链表,把所有加入的消息都一个一个串起来,每个消息都有一个唯一的ID和内容,这很简单,让它复杂的是从Kafka借鉴的另一种概念:消费者组(Consumer Group) (思路一致,实现不同)。
Redis基于内存存储,这意味着它会比基于磁盘的Kafka快上一些,也意味着使用Redis不能长时间存储大量数据。不过如果想以最小延迟实时处理消息的话,可以考虑Redis,但是如果消息很大并且应该重用数据的话,则应该首先考虑使用Kafka。
主从复制,是指将一台redis服务器的数据,复制到其他的redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower)。数据的复制时单向的,智能由主节点到从节点。主节点以写为主,从节点以读为主。
默认情况下,每台redis服务器都是主节点。一个主节点可以有多个从节点,一个从节点只有一个主节点。
配置方法:
主从复制主要作用:
主从复制共有三种模式:全量复制、基于长连接的命令传播、增量复制。
不足:主从模式不具备自动容错和恢复功能,主节点故障,集群则无法进行工作,可用性比较低,从节点升主节点需要人工手动干预。
Sentinel(哨兵)是用于监控Redis集群中Master状态的工具,是Redis高可用解决方案,哨兵可以监视一个或者多个redis master服务,以及这些master服务的所有从服务。 某个master服务宕机后,会把这个master下的某个从服务升级为master来替代已宕机的master继续工作。即使后来之前的master重启服务,也不会变回master了,而是作为slave从服务。
这里的哨兵有两个作用:
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。
不足:
Redis Cluster是一种服务器Sharding技术,redis 3.0版本开始正式提供。
Sentinel基本已经实现了高可用,但是每台机器都存储相同内容,很浪费内存,所以Redis Cluster实现了分布式存储。每台机器节点上存储不同的内容。
Redis 集群引入了哈希槽的概念,有 16384 个哈希槽(编号 0~16383)。集群的每个节点负责一部分哈希槽,每个 Key 通过 CRC16 校验后对 16384 取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
Redis Cluster集群具有如下几个特点:
Redis Cluster主要是针对海量数据+高并发+高可用的场景,海量数据,如果数据量很大,那么就建议用redis cluster,数据量不是很大时,使用sentinel就够了。redis cluster的性能和高可用性均优于哨兵模式。
对于过期的内容,Redis有两种删除方式。一是被动删除,当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key。二是主动删除,由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key。
Redis是内存数据库,全部数据都存放在内存中,但是内存的大小也是有限制的,不能无限使用,所以redis提供了相应的策略。
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key accordingly to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU
缓存穿透就是用户想要查询一个数据,发现redis内数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。布隆过滤器可以由Bitmaps实现,Redis4.0后官方提供了布隆过滤器的插件。
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。
但是这种方法会存在两个问题:
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
解决方案:
缓存雪崩,是指在某一个时间段,缓存集中过期失效,例如redis宕机、大量数据集中过期等。
解决方法: