- nosql:
- 方便扩展 高可扩展性
- 大数据量 高性能
- 数据类型多样,不需要事先设计,随去随用 高可用
redis remote dictionary server
- 支持网络、基于内存、可持久化(内存断电即失)、日志型、key-value
常用命令
- List item
- set [key] [value]
- get [key]
- keys [pattern]
- clear清屏
redisbenchmark官方性能测试工具
redis默认有16个数据库,通过select切换,DBSIZE查看数据库大小
- select [index]
- flushall清空所有数据库
- flushdb清空当前数据库
redis是单线程,基于内存,CPU不是性能瓶颈(多线程CPU上下文切换),瓶颈是机器内存和网络带宽
- 为什么单线程快:
基于内存
单线程避免上下文切换和竞态
IO复用/非阻塞IO
简单灵活的数据结构
单线程value比较大时,瓶颈会先出现在同步IO上 - redis6.0引入多线程
https://zhuanlan.zhihu.com/p/144805500 - Redis 选择使用单线程模型处理客户端的请求主要还是因为 CPU 不是 Redis 服务器的瓶颈,所以使用多线程模型带来的性能提升并不能抵消它带来的开发成本和维护成本,系统的性能瓶颈也主要在网络 I/O 操作上;而 Redis 引入多线程操作也是出于IO性能上的考虑,对于一些大键值对的删除操作,通过多线程非阻塞地释放内存空间也能减少对 Redis 主线程阻塞的时间,提高执行的效率。
用作数据库、缓存和消息中间件MQ
Redis-key
- exists [key]
- move [key] [index]//删除第index个数据库的key
- expire [key] [seconds]//设置过期时间
- ttl [key]//查看剩余时间
- type [key]//查看类型
string类型
- ppend [key] [value1] 往key对应的value中追加value1,不存在就创建
- strlen [key]查看value的长度
- incr [key] / incrby [key] [increment]
- decr [key] / decrby [key] [decrement]
- getrange [key] [start] [end] //相当与substr,闭区间,end可以为负数
- setrange [key] [offset] [val] 从offset开始替换
- setex(set with expire)设置过期时间
- setnx(set if not exist)不存在设置
- mset//设置多个键值对
- mget//获取多个键值对
- msetnx 原子性要么一起成功要么一起失败
- getset 获取并替换
List//可以存在重复值
- lpush [list] [value] 放入头部
- rpush [list] [value] 放入尾部
- lrange [list] [start] [end] 获取从头到尾
- lpop [list] 弹出头部
- rpop [list] 弹出尾部
- lindex [list] [index]
- llen [list]查看元素
- lrem [list] [count] [value] 删除指定数量的元素
- ltrim [list] [start] [end]修剪链表
- rpoplpush [srclist] [destlist]
- lset [list] [index] [value]更新
- linsert [key] [BEFORE|AFTER] [pivot] [value]在pivot前后插入value
消息队列的实现
set无序不重复集合
- sadd [key] [add]//
- smembers [key]
- sismember [key] value
- scard [key]获取个数
- srem [key] [value]移除元素
- srandmember [key] [count=1]获取指定个数元素的随机元素
- spop [key]随机移除元素
- smove [src] [dest] [value]
- sinter [key1] [key2]… 取交集
- sdiff [key1] [key2]… 取差集//left join
hash//比string更适合存储对象,对象有多属性即map
- Map集合,本质和string没有太大区别,key-value中 value值是一个map
- hset [hashkey] [mapkey] [mapvalue]
- hget [hash] [key]
- hmset [hash] [key] [value]…
- hmget [hash] [key]…
- hgetall [hash]//获取所有键值对
- hdel [hash] [key]
- hlen [hash]查看长度
- hexists [hash] [key]
- hkeys [hash]
- hvals [hash]
- hincrby [hash] [key] [increment]
- hsetnx [hash] [key] [value]
zset有序集合
- zadd [zset] [score] [value]
- zrange [zset] [start] [end]
- zrevrange [zset] [start] [end]
- zrangebyscore [zset] [minsocre] [maxsocre] [withsocres]从min到max显示value(带socre)
-inf,+inf表示最小和最大 - zrangebylex [zset] [minval] [maxval]对value按字典序排序(memcmp),分数必须相同
-,+表示最小和最大 - zrem [zset] [value]
- zcard [zset]获取数量
- zcount [zset] [minsocre] [maxscore]获取区间数量
geospatial地理位置//底层是zset
- geoadd [key] [longtitude] [latitude] [value]添加地理位置信息
- geopos [key] [value]获取指定经纬度
- geodist [key] [value1] [value1] [unit]//unit表示单位 km m
- georadius [key] [longtitude] [latitude] [radius] [unit] [withdist] [withcoord] [count] [cnt]获取经纬度半径内cnt个value
- georadiusbymember [key] [value] [radius] [unit] [withdist] [withcoord] [count] [cnt]获取value半径内cnt个value
- zrange
- zrem
redis事务不保证原子性,本质是一组命令的集合,所有命令都会被序列化
一次性、顺序性、排他性!执行一些列的命令!
不存在隔离级别的概念
- 开启事务(multi)
- 命令入队(命令)
- 执行事务(exec/discard)
如果命令代码错误,命令都不会被执行
如果命令代码执行错误,其他命令还会正常 执行(不满足原子性)
- 悲观锁:
每次都加锁 - 乐观锁:
不加锁,在更新时判断是否被修改,MySQL的version(MVCC)
redis利用watch实现乐观锁, - 在执行事务前watch,若发生修改事务就执行失败,unwtach,再watch再执行事务,类似自旋锁
redis.conf配置文件
- ind [ip] 127.0.0.1本地
- port [port]
- config set [requirepass] [password]设置密码
- config get [requirepass]
- auth [password]登录密码
- maxmemory-policy 处理策略lru
redis持久化 RDB/AOF
- RDB是一种快照存储持久化方式,具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中,默认保存的文件名为dump.rdb,而在Redis服务器启动时,会重新加载dump.rdb文件(优先载入aof,因为aof更完整)的数据到内存当中恢复数据
- RDB执行方式
- save。同步操作,会阻塞Redis。
- bgsave。调用linux的fork(),然后使用新的线程执行复制。但是fork期间也会阻塞Redis,但是阻塞时间通常很短。服务器可以异步处理客户端指令
- 自动保存。Redis配置文件中设置了自动保存的触发机制,可以自定义修改,运行原理同bgsave。
- 触发机制:save规则满足;flushall;退出redis;
-
优点:
适合大规模的数据恢复
对数据的完整性要求不高 -
缺点:
需要一定的时间间隔进行操作,
fork会占用一定的时间和和内存,save会阻塞服务器,但不占用内存 -
与RDB存储某个时刻的快照不同,AOF持久化方式会记录客户端对服务器的每一次写操作命令,并将这些写操作以Redis协议追加保存到以后缀为aof文件末尾,在Redis服务器重启时,会加载并运行aof文件的命令,以达到恢复数据的目的。
AOF以日志的形式记录每个写操作,追加在aof文件中appendonly.aof,启动时重构,默认不开启 -
appendonly.aof出错的话,redis会无法启动,redis提供redis-check-aof修复aof文件
-
redis-check-aof --fix appendonly.aof
-
优点:
每一次修改都同步,文件完整性会更好
每秒同步可能丢失每秒的数据
从不同步,效率最高 -
缺点:
数据文件来说,aof远大于rdb,修复速度也比rdb慢
运行效率比rdb慢,每个写请注都有IO操作,默认rdb -
aof文件太大,加载aof文件恢复数据时,就会非常慢,为了解决这个问题,Redis支持aof文件重写,通过重写aof,可以生成一个恢复当前数据的最少命令集。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。
-
AOF重写方式也是异步操作,即如果要写入aof文件,则Redis主进程会forks一个子进程来处理
-
no-appendfsync-on-rewrite可以设置是否开启重写,这种方式会在每次fsync时都重写,影响服务器性以,因此默认值为no,不推荐使用。
-
客户端向服务器发送bgrewriteaof命令,也可以让服务器进行AOF重写。
-
rdb:会frok子进程
-
aof:不会frok子进程,重写机制会frok子进程
redis消息订阅模式
- PUBLISH [channel] [message] client1在频道发布消息
- SUBSCRIBE [channel] client2订阅频道阻塞等待发布的消息
- 实现原理:服务端维护一个字典,字典的键对应channel,值对应订阅这个channel的client链表,当有客户端在往频道内发送消息时,服务器就遍历链表,将消息发送给订阅者
redis主从复制(读写分离),减缓服务器压力
- 数据复制是单向的,主节点到从节点,Master以写为主,slave以读为主
- 作用:
数据冗余,热备份
故障恢复,节点切换
均衡负载,读写分离,提高并发量
高可用(集群) - info replication查看当前库的信息,默认每个服务器都是主节点
- 命令行配置:SLAVEOF [IP] [PORT]在从机中设置主机,重启失效 SLAVE no one恢复成主机
- 配置文件配置: replicaof [ip] [port]
- 主机断开时,从机仍能读,但是无法写,因为只能主机写
- 重连会按照配置文件设置启动,因此通过命令配置会失效,需重新配置,主要变为从机,数据会复制回来
复制原理: - slave链接成功后,会发送sync同步命令,Master收到指令,fork启动后台存盘子进程执行bgsave生成rdb文件,同时主进程继续接受的修改数据集的命令并存入缓冲区,在后台进程执行完毕之后,master将传送RDB数据文件到slave,并讲缓冲区的命令也发送至slave,完成一次完全同步
- 全量复制:完全同步
- 增量复制:master将手机到的修改命令依次同步给slave
- 多级从节点:从节点2附属于从节点1,数据复制从主节点到从节点1到从节点2…
哨兵模式(自动选主节点)
- 哨兵是独立的进程,通过发送命令,等待redis服务器相应,从而监控运行的多个redis实例
- 多哨兵模式,互相监督
- 配置哨兵文件sentinel.conf
- sentinel monitor [redisname] [masterip] [masterport] [1]//1代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作
- 主观下线:哨兵发现出错
- 客观下线:当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时。
- 客观下线后,哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机
- 主机出错回归会变为从机
- 优点:
- 哨兵集群,基于主从服务,拥有主从模式的优点
- 主从可以切换,故障可以转移
- 主从模式的升级,自动切换,更健壮
- 缺点:
- 通过配置文件设定,在线扩容麻烦
- 哨兵模式配置麻烦
https://www.cnblogs.com/kevingrace/p/9004460.html
redis缓存穿透和雪崩
- 缓存穿透:查询数据库没有的数据,会越过缓存,请求数据库,给数据库造成压力
- 解决方案:
- 布隆过滤器,对所有可能查询的参数已hash形式存储,在控制层进行校验,避免从对底层查询系统的查询压力
- 缓存空对象,占空间,缓存层和数据层不一致
- 缓存击穿:一个key非常热点,在缓存失效瞬间,大量数据直接访问数据库
- 解决方案:
- 设置热点数据用不过期
- 加互斥锁,分布式锁,保证每个key只有一个线程去查询后端服务
- 缓存雪崩:某一个时间段,缓存集中过期失效,redis宕机
- 解决方案:
- redis高可用:增设redis,异地多活
- 限流降级:通过加锁或队列控制读数据库和写缓存的数量
- 数据预热:设置失效时间,使失效时间点尽量均匀