Redis-狂神、慕课
定义:内存中的数据结构可持久化的存储系统,用作数据库、缓存、消息中间件。支持多类型数据结构(字符串、散列、列表、集合、有序集合、范围查询、索引半径查询),
内置了复制、LUA脚本、LRU驱动事件、事务和不同级别磁盘持久化,并通过Redis哨兵和自动分区提高可用性.
基本知识
Redis五大基础 数据类型:List、set、Zset、Hash、String
单机、缓存+mysql+垂直拆分(读写分离)、分库分表+水平拆分+mysql集群
用户->路由网关->负载均衡(主备机)->服务器(123)->mysql(1-5) 独立的缓存服务器、移动信息服务器、Hadoop服务器、实时通信服务器
为什么用NoSQL?
用户的个人信息、社交网络、地理位置、用户产生数据、日志增长这些数据NoSQL处理。
3V3高 海量多样实时 高并发高可托高性能
NoSQL:不仅仅是数据、没有固定的查询语言、简直对存储列存储文档存储图形数据库、最终一致、
CAP定理和BASE异地多活、高性能、高可用、高可扩展性
NoSQL四大分类:新浪Redis 美团Redis+Tair 阿里百度Redis+Memcache(Memcache支持简单数据类型,需要客户端自己处理复杂对象)
Redis 默认16个库,select 0-15,默认0
NoSQL四大分类-类型 | 代表 | 特点 |
---|---|---|
键值对数据库 | Redis、Memecache | |
列存储数据库 | Hbase、Cassandra | HBase分布式文件系统 |
文档数据库 | MongoDB、CouchDB | json:MongoDB,基于分布式文件存储的数据库,处理大量的文档,介于关系型数据库和非关系数据库中 |
图形数据库 | Neo4J、FlockDB 、infoGrid、infinite |
Redis作用:持久化存储,内存是断电即失、效率高可用于高速缓存、发布订阅系统、计时器计数器
Redis默认有16个数据库
redis单线程模型,在规避了cpu切换损耗的同时也能 保证数据顺序提交,不需要考虑数据一致性问题,单线程模型是因为文件事件处理器file event handler是单线程的,Redis底层采用了Epoll这款多路复用IO模型,非阻塞同步IO。
Memcache 是多线程模型通过cas(比较并交换java.util.concurrent包中无论是ReentrantLock内部的AQS,还是各种Atomic开头的原子类,内部都应用到了CAS)保证数据一致性
redis瓶颈是机器的内存和网络带宽,redis是C语言写的,官方提供数据为10,0000+QPS,不比key-value的Memcached差,对于内存系统说,如果没有上下文切换效率就是最高的。
集群种类
安装Redis以及基础命令
redis-benchmark是官方自带的性能测试工具
String字符串类型
user:{id}:{filed}巧妙设计 set user:1:name zhangyingqi user:2:age 24
mget user:1:nqme user:1:age
get db
getset db mongdb
get db
keys like*
keys *
SETINX age 18 不存在age这个KEY18会被设置进去
ttl age 30 设置age这个key过期时间为30S
StrLEN age 查看key的长度
incr age 累加key的值 ++
decr key 累减值 –
INCRBY key 数值 在基础上增加数值
DECRBY key 数值 累减
应用场景
共享⽤户Session:⽤户重新刷新⼀次界⾯,可能需要访问⼀下数据进⾏重新登录,或者访问⻚⾯缓存Cookie,但是可以利⽤Redis将⽤户的Session集中管理,在这种模式只需要保证Redis的⾼可⽤,每次⽤户Session的更新和获取都可以快速完成。⼤⼤提⾼效率
缓存功能
计数器
List
redis中list可以玩成栈、队列、阻塞队列
所有的list命令都是L
LPUSH list one
LRANGE list 0 -1 输出所有
LRANGE list 0 1
RPUSH list zyq
Lrange list 0 -1
LPOP RPOP
Lindex list 1 获取list某一个值通过下标
Llen list 返回列表长度
flush db
Lrem list 1 value 移除list集合中指定个数的value,精确匹配
ltrim list 1 2 截取指定的长度值,list只剩下截取的数
linsert list after one ten
使用场景:消息队列 栈 、相关推荐
Set
set中的值不能重复,Set是⽆序集合,会⾃动去重的
sadd myset hello
SMEMBERS myset 查看myset中所有值
scard myset 查看集合中的个数
SMEMBERS myset 查看集合中元素
srem myset “hello” 移除集合中的值
SRANDMEMBER myset 随机筛选出来一个值
spop myset 随机删除指定的key
sdiff set1 set2 差集 set中有set2没有
SINTER set1 set2 交集
SUNION set1 set2 并集
使用场景:微博共同好友、推荐
Hash
Map集合 key-Map
hset myhash field1 tom
hget myhash field1 返回tom
hmset myhash field1 hello field2 world
hgetall myhash
Hash本质上和String没有本质的区别,只是一个简单的key-value
hdel myhash field1 删除hash指定的字段对应的value也就消失
hlen myhash
HEXISTS myhash field1
hkeys myhash 只获得所有的key
hvals myhash 只获得所有的value
HINCRBY myhash filed1 1 自增
HEXISTS field1 tom 返回1存在0不存在
HDEL myhash field1 map中的删除属性
使用场景:适合存储经常变动的消息-用户信息、帖子点赞数评论数点击数、缓存近期热帖内存、用户历史行为 hash适合对象的存储 age name
Zset有序集合 zset k score v
zadd myset 1 one
zrange myset 0 -1 withscores
zadd salary 1200 xiaohong
zadd salary 1500 xiaoming
zarangebyscore salary - inf +inf 升序排序
zarangebyscore salary - inf +inf whitscores
zrem salary xiaohong
zcard salary 获取有序集合个数
zcount myset 1 3 获取指定区间的成员数量
使用场景:热榜、收藏贴、贴关系、去重计数
三种特殊数据类型
+
geospatial 地理位置
china:key
geoadd china:city 经度 维度 地点名字
geopos china:city beijing chongqing 查看地点的经度纬度 获取当前定位一对坐标值
geodist china:city beijing shanghai 地点之间的直线距离 mi英里 ft英尺
georadius china:city 110 30 100km withdist|whithcoord 以点为半径查询城市带有纬度|直线距离
使用场景:我附近的人,获得所有附近的人的地址、定位
georadius china:city 110 30 100km withcoord count 2 查询指定数量
georadiusbymember china:city shanghai 400 km 查看以地点为中心距离多少的周边城市
geohash China:city beijing chongqing 返回一个或多个位置元素用hash表示 返回经纬度->字符串返回
zrange china:city 0 -1
+
Hyperloglogs
基数统计的算法
应用场景:网页的UV(一个人访问一个网站多次算一次)
PFadd myjihe1 a c b d e f
PFcount myjihe1
PFadd myjihe2 a e r t y
PFcount myjihe2
PFMerge myjihe3 myjihe1 myjihe2 将集合合并
+
Bitmaps
位存储,数据结构,都是操作二进制位来进行记录,只有01状态
位图是⽀持按 bit 位来存储信息,可以⽤来实现 布隆过滤器
setbit sign 0 1
setbit sign 1 0
getbit sign 1 查看某一天是否打卡
bitcount sign 0 1 在0-1区间统计打卡天数
365天=365bit 46字节,一字节等于8bit
+
Pipeline
可以批量执⾏⼀组指令,⼀次性返回全部结果,可以减少频繁的请求应答
事务
本质:一组命令的集合,一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行. 一次性、顺序性、排他性执行一系列命令.
Redis单条命令是保存原子性的,但是事务 不把证原子性。
Redis事务没有隔离级别的概念
开启事务(multi)->命令入队(… set k1 v1、 get k1、 set k3 v3、)->执行事务(exec执行|DISCAED放弃所有事务)
java错误:编译型异常、运行时异常(部分错误命令会抛出异常)
监控->Watch
悲观锁:无论做什么都加锁
乐观锁:不上锁
set money 100
set out 0
watch money
multi
decrby money 10
incrby out 10
exec
测试多线程修改值,使用watch可以当做redis乐观锁操作
unwatch 解锁
如果发现事务执行失败,先解锁;获取最新的值,再次监视;比对监视的值是都发生变化,如果变化,执行失败
秒杀乐观锁使用watch
Jedis
Jedis是Redis官方推荐的java连接开发工具,使用java操作Redis中间件
Jedis:采用直连,多个线程操作,不安全,避免不安全使用Jedis pool连接池 像BIO模式
lettuce:采用netty,实例可以再多个线程中进行共享,不存在线程不安全的情况,可以减少线程数据 像NIO模式
序列化:默认的序列化方式是JDK序列化,有可能是JSON序列化
持久化,在规定时间内执行多少次操作,则会持久化到文件 RDB AOF (RDB更适合做冷备,AOF更适合做热备)
redis是内存数据库,如果没有持久化,那么数据断电及失
如果只做缓存,不需要任何持久化,只希望 数据在服务器运行时存在
RDB-全量备份
Redis 会单独创建fork一个子进程进行持久化,会将数据写到一个临时文件中,待持久化过程结束,在用这个临时文件替换上次持久化好的文件,整个过程中,主进程是不进行IO操作的,确保了极高的性能,如果需要大规模数据恢复,对于数据恢复的完整性不是非常敏感,RDB比AOF方式更高效,RDB缺点是最后一次持久化后数据可能丢失.
默认是RDB,一般不需要修改这个配置.
触发机制:save规则满足、fushall、退出redis等情况下会自动触发RDB,备份自动生成dump.rdb
如何恢复rdb文件:rdb文件 放在redis启动目录即可
优点:适合大数据恢复、对数据的完整性要求不高
缺点:需要一定时间间隔进程操作,redis意外死机,最后一次数据没有、fork进程占用内容空间
主从复制中,rdb就是备用,在从机上面
AOF-增量定时
将所有命令记录下来,history恢复时候会将这个文件全部执行一遍
配置文件配置:
[appendfsync always]每次修改都会sync消耗性能
[appendfsync everysec]每秒执行一次sync,可能会丢失数据
[appendfsync no]不执行sync,这个时候操作系统自己同步数据,速度最快
Redis 会单独创建fork一个子进程,以日志的形式来记录每个写操作,将执行过得所有指令记录下来,只需追加文件不可以修改文件(appendOnly.aof),redis启动之初会读取改文件重新构建数据。
redis提供工具检查aof文件是否有错位redis-check-aof —fix appendOnly.aof
优点:每一次修改都同步,文件完整性好,从不同步效率最高,每秒同步数据,可能会丢失1s数据
缺点:RDB恢复数据比AOF快,AOF是IO操作,慢
Redis发布订阅
通信、队列
Redis发布订阅pub|sub是一种消息通信模式
Redis客户端可以订阅任意数据的频道
消息发布者(redis cli)->发布消息->[队列redis server]{消息订阅者去抢 redis cli}
Redis是C语言实现的,通过 PUBLISH SUBSCRIBE PSUBSCRIBE 实现发布和订阅功能
主从复制
Master|Slave
单个redis并发量上限是5-6W
主从复制,读写分离,80%情况下都市进行读操作,减缓服务器压力,一主二从
配置环境单机多集群:
复制配置文件修改信息[端口、log文件名、pid名字、dump.rdb名字]、启动
全量复制:salve服务接口道数据库文件数据,将其存盘加载到内存中
增量复制:master继续讲收集到新的传递给salve
原理:
选主的策略简单来说有三个:slave 的 priority 设置的越低,优先级越⾼;同等情况下,slave 复制的数据越多优先级越⾼;相同的条件下runid 越⼩越容易被选中;
搭建主从复制(读写分离)
让这个master机器去写,数据同步给别的slave机器,他们都拿去读,分发掉⼤量的请求
无磁盘化复制原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
步骤: 实验阶段不能使用在生产环境
1、vim redis.conf
2、repl-diskless-sync yes
哨兵模式Sentinel
if master kill ->哨兵模式
选举新的master组成新的主从复制,多个哨兵
cp sentinel.conf /usr/local/redis/ redis.conf同目录下
哨兵模式核心配置文件sentinel.conf [sentinel monitor 被监控名称 host 6379 1(哨兵数)]
sentinel auth-pass master-name password
sentinel down-after-milliseconds master-name 30s
sentinel parallel-syncs master-name 并行同步的数量
sentinel failover-timeout master-name 18s
启动[redis-sentinel config/sentinel.conf]
优点:哨兵集群,基础主从复制,所有主从复制优点均有、主从可以切换,故障可以转移,系统可用性好、哨兵模式自动,健壮
缺点:redis不好在线扩容,集群容量达到上限,麻烦、哨兵配置麻烦选择性多
图解哨兵
redis-cli -p 端口号 连接哨兵
master-name下的master信息检查 sentinel master master-name
master-name下的slaves信息检查 sentinel slaves master-name
master-name下的哨兵节点信息检查 sentinel sentinels master-name
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
Redis缓存穿透和雪崩
缓存穿透(查不到):缓存 没有,直接访问数据库也没有 解决方法:缓存层加缓存null对象、布隆过滤器
缓存击穿(查太多次):是指一个key非常热点,并发访问一个点,key失效瞬间,持续就穿破缓存,直接请求数据库,写缓存,会导致数据库瞬间压力过大 解决方法:设置热点数据永不过期、加互斥锁(使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有锁的权限,这种方式将高并发压力转移到分布式锁,因此分布式锁考验很大)
缓存雪崩:指某段时间内,缓存集中过期失效,Redis宕机 解决办法:redis高可用搭建集群异地多活、限流降级springCloud、数据预热(在正式部署之前,可能的数据预先访问一遍,大量数据加载到缓存中,将发生大量访问前手动触发加载缓存不同的key,设置过期时间,让缓存失效的时间点尽量均匀)
阻塞与非阻塞
缓存过期机制
1、定期删除
2、vim redis.conf -> hz 一般设置10
3、惰性删除(过期的key请求 ,检测是否过期,删除)不怎么占用CPU但是占用内存
4、内存淘汰管理机制,Memory management 、maxmemory
内存淘汰策略:
内存淘汰策略 | 含义 |
---|---|
noeviction | 不淘汰任何数据,当内存不足时,执行缓存新增操作会报错,这种策略下可以保证数据不丢失,它也是 Redis 默认的内存淘汰策略 |
allkeys-lru | 淘汰整个键值中最久未使用的键值,这也就是我们常说的LRU算法 |
allkeys-random | 随机淘汰任意键值 |
volatile-lru | 淘汰所有设置了过期时间的键值中最久未使用的键值 |
volatile-random | 随机淘汰设置了过期时间的任意键值 |
volatile-ttl | 优先淘汰设置了过期时间中更早过期的键值 |
分布式锁
setnx aobing
expire aobing
del aobing
#面试题
什么是redis
redis数据类型
redis使用的好处
redis是单线程的为什么怎么高效?
持久化机制,各自优缺点
redis常见性能问题和解决方案
redis过期的删除策略
内存淘汰策略 | 含义 |
---|---|
noeviction | 不淘汰任何数据,当内存不足时,执行缓存新增操作会报错,这种策略下可以保证数据不丢失,它也是 Redis 默认的内存淘汰策略 |
allkeys-lru | 淘汰整个键值中最久未使用的键值,这也就是我们常说的LRU算法 |
allkeys-random | 随机淘汰任意键值 |
volatile-lru | 淘汰所有设置了过期时间的键值中最久未使用的键值 |
volatile-random | 随机淘汰设置了过期时间的任意键值 |
volatile-ttl | 优先淘汰设置了过期时间中更早过期的键值 |
同步机制
pipeline好处
集群原理
什么情况下会导致整个集群不可用
redis支持的java客户端有那些
jedis | redisson |
---|---|
Jedis 是 Redis 的 Java 实现的客户端 | Redisson 实现了分布式和可扩展的 Java 数据结构 |
API 提供了比较全面的 Redis 命令的支持 | 功能较为简单,不支持 字符串操作,不支持排序、事务、管道、 分区等 Redis 特性。 |
对于分布式,功能复杂不如 jedis | Redisson 的宗旨是促进使用者对 Redis 的关注分离,让使用者能够将精 力更集中地放 在处理业务逻辑上 |
哈希槽
redis主从复制模型
redis如何设置密码及验证密码
redis集群写操作丢失
集群如何复制的
集群最大节点个数
集群如何选择数据库
redis连通性
redis事务
事务命令
key的过期时间和永久有效设置
内存如何优化
回收进程如何工作
降低redis内存使用情况
redis内存使用完后会发生什么
redis实例最多存放keys,string list set sorted set最多存放多少数据
BD2kw数据,redis20w如何保证热点数据
保证缓存和数据库一致性方案
四种同步策略 |
---|
先更新缓存后更新数据库 |
先更新数据库再更新缓存 |
先删除缓存,在更新数据库 |
先更新数据再删除缓存 |
假如 Redis 里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
redis最适合的场景
秒杀库存扣减
app首页访问流量高峰
与Memcache区别
名称 | 特点 |
---|---|
Redis | 单核;单线程非阻塞同步IO; 有集群模式,主从模式;可持久化提供高可用服务;多数据结构 |
Memcache | 多核;多线非阻塞程异步IO ;无原生集群需要客户端实现往集群分片写入数据;KV存储;内存存储,没有持久化和主从同步功能;key小于250B,value小于1MB,过期时间小于30day:失效是延迟失效;使用LRU进行数据剔除 |
Redis进阶
后期补充Redis Module(BloomFilter,RedisSearch,Redis-ML)
Tair的多线程实现更加优雅。如下图
多线程种类 | 职责 |
---|---|
Main Thread | 负责客户端连接建立 |
IO Thread | 负责请求读取、响应发送、命令解析等(读取用户的请求并进行解析,之后将解析结果以命令的形式放在队列中发送给Worker Thread处理) |
Worker Thread | 线程专门用于事件处理(Worker Thread将命令处理完成后生成响应,通过另一条队列发送给IO Thread) |