介绍
是一个开源的,内存中的数据结构存储系统(基于内存存储),可以用作数据库,缓存和消息中间件.Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。 类型 字符串(strings) 散列(hashes) 列表(lists) 集合(sets) 有序集合(sorted sets) bitmaps hyperloglogs 地理空间(geospatial) 内部 内置了复制(replication) LUA脚本(Lua scrption) LRU驱动事件(LRU eviction) 事务(transations) 不同级别的磁盘持久化(persistence) Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)
优点
1.读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。 2.支持数据持久化,支持AOF和RDB两种持久化方式。 3.支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。 4.数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。 5.支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
类型
string
set set key value get get key mset mset key value key value mget mget key key 实用场景对于计算日活,月活(通过位运算)Json 普通文本 setbit key bit value bitconut key PV(访问量) 用户每次刷新算一次 UV(独立访客) 同一个ip再24小时内算一次 help @string
hash(类似于二维表)
场景 表记录存储 hset hset key field value hget hget key field hmset hmset key field value [field value] hmget hmget key field [field] hgetAll hgetAll key hdel hdel field [field]
list(双向链表)
场景 消息队列 lpush lpush key value [value...] rpush rpush key value [value...] blpop blpop key [key ...] timeout brpop brpop key [key ...] timeout lrange 获取 lrange key start(起始下标) stop(结束下标) llen 获取条数 llen key lrem lrem key count value count>0 从前向后删除count个value =0 删除所有 <0 从后向前删除 lset lset key index value
set(集合的交集等)
场景 社交软件 交集 并集 差集 加关注 取消关注 sadd key member [member...] smembers key 获取set类型数据 scard key 获得条数 srem key member [member...] 删除数据 sdiff key [key...] 差集 sunion key [key...] 并集 sinter key [key...] 交集
sorted set(通过分数值进行排序,升序)
场景 排行榜(音乐排行榜) zadd zadd key score member [score menmber...] zrange 获取 zrange key start end zcard 获取条数 zcard key min max zrem 删除 zrem key member [member] help @sorted_set
通用命令
help @generic 操作失效时间 expire <key> <ttl> 秒 pexpire key ttl 毫秒 pexpireat <key> <timestamp> 指定毫秒数时间戳 expireat <key><timestamp> timestamp指定的秒数时间戳 删除 del key ttl ttl key 查看失效时间 -1 代表永久 type 类型 help @cluster
关系型数据库与非关系型数据库
关系型数据库
就是二维表格模型。一张二维表的表名就是关系,二维表中的一行就是一条记录,二维表中的一列就是一个字段 优点 容易理解 使用方便,通用的sql语言 易于维护,丰富的完整性大大降低了数据冗余和数据不一致的概率 缺点 磁盘I/O是并发的瓶颈 海量数据查询效率低 多表的关联查询以及复杂的数据分析类型的复杂sql查询,性能欠佳 横向扩展困难,无法简单的通过添加硬件和服务节点来扩展性能和负载能力,当需要对数据库进行升级和扩展时,需要停机维护和数据迁移
非关系型数据库
分布式,一般不保证遵循ACID原则的数据存储系统。键值对存储,结构不固定。 优点 根据需要添加字段,不需要多表联查。仅需id取出对应的value 适用于SNS(社会化网络服务软件。比如(微博) 严格上讲不是一种数据库,而是一种数据结构化存储方法的集合 缺点 只适合存储一些较为简单的数据 不合适复杂查询的数据 不合适持久存储海量数据 比较
java操作redis
Lettuce和Jedis的区别
Jedis: 采用的直连,多个线程操作的话,是不安全的 Lettuce: 采用netty,实例可以再多个线程中进行共享,线程安全
自定义模板解决序列化
JdkSerializationRedisSerializer 存储二进制字节码,序列化功能,反序列化不需要提供类型信息(class),缺点是序列化结果非常庞大,是json的5倍,消耗Redis服务器大量内存 StringRedisSerializer 存储String Jackson2JsonRedisSerializer 使用Jackson对象序列化功能,速度快,字符串短小,缺点,必须提供序列化对象类型信息(.class),只在反序列化过程中用到此信息。 GenericJackson2JsonRedisSerializer 通用型序列化,这种序列化方式不用自己手动指定对象的 Class
数据持久化
通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化
Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以 Redis 提供了持久化功能! 默认使用的是RDB模式
RDB
优点 1、适合大规模的数据恢复! 2、对数据的完整性要求不高! 缺点 1、需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改数据就没有的了! 2、fork进程的时候,会占用一定的内容空间!
AOF
优点 1、每一次修改都同步,文件的完整性会更加好! 2、每秒同步一次,最多会丢失一秒的数据! 3、从不同步,效率最高的 缺点 1、相对于数据文件来说,aof远远大于 rdb (aof文件比rdb文件大) ,修复的速度也比 rdb慢! 2、Aof 运行效率也要比 rdb 慢,所以我们redis默认的配置就是rdb持久化!
主从复用
是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower) 主要作用 ①数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。 ②故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。 ③负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。 ④高可用(集群)基石:主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
哨兵
能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库 优点 ①哨兵集群,基于主从复制模式 ,所有的主从配置优点,它全有 ②主从可以切换,故障可以转移 ,系统的 可用性 就会更好 ③哨兵模式就是主从模式的升级,手动到自动,更加健壮! 缺点 不好在线扩容 的,集群容量一旦到达上限,在线扩容就十分麻烦!
如何应对缓存穿透、缓存击穿、缓存雪崩问题
key的过期淘汰机制
Redis可以对存储在Redis中的缓存数据设置过期时间,比如我们获取的短信验证码一般十分钟 过期,我们这时候就需要在验证码存进Redis时添加一个key的过期时间,但是这里有一个需要格 外注意的问题就是:并非key过期时间到了就一定会被Redis给删除。
定期删除
Redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 Key,检查其是否过期,如果过 期就删除。为什么是随机抽取而不是检查所有key?因为你如果设置的key成千上万,每100毫秒 都将所有存在的key检查一遍,会给CPU带来比较大的压力。
惰性删除
定期删除由于是随机抽取可能会导致很多过期 Key 到了过期时间并没有被删除。所以用户在 从缓存获取数据的时候,redis会检查这个key是否过期了,如果过期就删除这个key。这时候就 会在查询的时候将过期key从缓存中清除。
内存淘汰机制
仅仅使用定期删除 + 惰性删除机制还是会留下一个严重的隐患:如果定期删除留下了很多已 经过期的key,而且用户长时间都没有使用过这些过期key,导致过期key无法被惰性删除,从而 导致过期key一直堆积在内存里,最终造成Redis内存块被消耗殆尽。那这个问题如何解决呢?这 个时候Redis内存淘汰机制应运而生了。Redis内存淘汰机制提供了6种数据淘汰策略:
-
volatile-lru :从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
-
volatile-ttl :从已设置过期时间的数据集中挑选将要过期的数据淘汰。
-
volatile-random :从已设置过期时间的数据集中任意选择数据淘汰。
-
allkeys-lru :当内存不足以容纳新写入数据时移除最近最少使用的key。
-
allkeys-random :从数据集中任意选择数据淘汰。
-
no-enviction(默认) :当内存不足以容纳新写入数据时,新写入操作会报错。
缓存击穿
高并发的情况下,某个热门key突然过期,导致大量请求在Redis未找到缓存数据,进而全部去访问DB请求数据,引起DB压力瞬间增大。 解决方案:
1.如果要求数据必须是新数据,则最好的方案则为热点数据设置为永不过期,然后加一个互 斥锁保证缓存的单线程写
缓存穿透
缓存穿透是指查询缓存和DB中都不存在的数据.比如用户需要查询一个数据,但是redis中没有 ,直接去请求数据库,如果很多用户同时去请求数据库,就会给数据库带来很大压力
解决方案:
1.利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试 2.采用异步更新策略,无论key是否取到值,都直接返回 3.提供一个能迅速判断请求是否有效的拦截机制.比如,利用布隆过滤器
缓存雪崩
缓存中如果大量缓存在一段时间内集中过期了,这时候会发生大量的缓存击穿现象,所有的请求都落在了DB上,由于查询数据量巨大,引起DB压力过大甚至导致DB宕机 解决方案: 1.给缓存的失效时间,加上一个随机值,避免集体失效 2.使用互斥锁,但是该方案吞吐量明显下降了 3.设置热点数据永远不过期。 4.双缓存。
Redis事务相关命令
Redis的事务总是具有ACID中的一致性和隔离性,其他特性是不支持的。
-
edis 不支持回滚,“Redis 在事务失败时不进行回滚,而是继续执行余下的命令”, 所以 Redis 的内部可以保持简单且快速。
-
如果在一个事务中的命令出现错误,那么所有的命令都不会执行;
-
如果在一个事务中出现运行错误,那么正确的命令会被执行。
事务管理(ACID)概述
-
原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
-
一致性(Consistency) 事务前后数据的完整性必须保持一致。
-
隔离性(Isolation) 多个事务并发执行时,一个事务的执行不应影响其他事务的执行
-
持久性(Durability) 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响