Redis(单机,单进程,缓存,数据库)
redis是单进程,单线程,单实例
redis里面分了16个分区,我们通过自己的需要进行分区的设置
二进制安全:与外界交互,只拿字节流
启动时在redis-cli启动时添加–raw,会对编码格式化,可以拿出汉语不变化,不添加默认16进制获取
flushall:清库
expire:过期命令
expireat:定时,指定时间过期
redis安装:
utlis下的install_server.sh安装
配置文件地址在/etc/redis/里面
日志文件/var/log/redis_6379.log
数据目录:/var/lib/redis/6379
key
type:描述value的类型
object:encoding:编码类型
value
String Byte
字符串
ttl:查看过期时间
set:存入数据
ex:多少秒后过期,访问一次过后不会延长
nx:只能新建不能覆盖
XX:只能更新不能新建
get:获取数据
mset:批量插入
mget:批量获取
msetnx:批量插入,并且遇到错误全部回滚
getset:取回老的值,覆盖新的值,减少数据的优化
append:追加
getrange:截取value的值并返回
正反向索引
setrange:对索引处进行覆盖
strlen:获取长度
数值
incr:对数值类型进行加一
incrby:累加
decr:减一
decrby:减去对应的数
incrbyfloat:加小数
bitmap
方法
setbit:基于ascli编码,对相应的字节进行设置
常识
字符集:标准的ascli,其他为他的扩展
bitpos:寻找第一个二进制为所处的位置,开始位置和结束位置为字节空间,比如bitpost k1 0 0 1,表示,0在第0个字节空间到第一个直接空间第一次出现的位置索引
bitcount:统计开始字节空间到结束直接空间中1出现的个数
bitop:把bit进行二进制与的操作:有0则0 全1为1 或的操作:有1则1,全0为0
场景
1、有用户系统,统计用户的登录天数,且窗口随机
mysql统计登录天数,每个用户的信息量特别大
redis通过二进制统计天数,一个用户一年只需要通过大约50个字节就可以存储,打打节约内存
2、京东是自己的,618做活动,只要登录就送礼物
大库备货多少礼物
假设京东有2e用户
用户: 冷热用户/忠诚用户
活跃用户统计!随机窗口
活跃用户的统计,比如说1号-3号联系登录
技术:去重
List
存入的时候,可以有重复
栈:同向命令
队列:反向命令
数组
阻塞,单播队列 fifo:先进先出
lpush:第二个存入的数据放入第一个左边
rpush:第二个存入的数据放入第一个右边
lpop:取出最左边的数据
rpop:取出最右边的数据
lrange 取出list区间的数据,redis具有反向索引的功能
lindex:取出一个索引
lset:更新指定索引的数据
lrem:移除指定个数的数据。
blpop:阻塞获取,fifo
根据count来判断,如果count是正数,从前往后减去,如果是负数的话,从后往前减去
linsert:在指定的数据加入数据
llen k3:统计长度
hash
设置时key对应的是fieid value
hset:往hash里面添加数据
hmset:批量插入
hget:获取存入的值
hmget:批量获取存入的值
hkeys:获取所有的fieid
hvals:获取所有的value
hgetall:获取所有的fieid和value
hincrby:进行整数的运算
hincrbyfloat:进行小数运算,可以加法也可以减法
场景
对fieId进行数值运算,点赞,收藏,浏览次数
set
存入的时候,不可以重复,不维护排序,不维护插入的位置
sadd:添加元素,并且做去重处理
smembers:取出该集合下面的所有元素
srem:移除集合里面的元素
smembers:取出所有的成员
sinter:取出对应集合的交集
sinterstore:取出对应集合的交集,并且赋值给新的集合(需要提供一个新的key名称)
sunion:取出对应的并集
sunionstore:去出对应的并集,并且赋值给新的集合(需要提供一个新的key名称)
sdiff:取出差集合,前面的集合和后面集合有差别的元素
spop:取出一个任意元素
SRANDMEMBER key count
正数:取出一个去重的结果集(不能超过已有集)
负数:取出一个带重复的结果集,一定满足你要的数量
如果:0,不返回
应用:
抽奖:10个奖品 ,用户:<10 >10,中奖:是否重复
sorted_set
去重,并且排序
物理内存左小又大,不随着命令发生变化
zadd:设置属性,设置方式为 key score member,类似于hash,设置的score为数字
zrange:取出区间内的元素,可以设置参数withscores来去除前面的排序元素
zrangbyscore:按照分值去取
zrevrange:按照倒叙取出元素
zscore:通过元素取出score
zrank:通过元素取出该元素在集合中的排名
zincrby:通过元素对score进行加减
集合操作
对已有元素的score进行操作
zunionstore:
属性
weights:每个key的占比
aggreate:指定聚合函数
场景:歌曲排行榜
排序怎么实现,正删改查的熟读
skip list:跳跃表,随机造层
pipeline的使用
可以进行多条语句的注入,提高效率
发布订阅pubsub的使用
订阅的只能收到接收之后的
publish:推送消息
subscribe:接收消息
transcations事务
因为redis是单进程的,两个客户端,一个事务的失败不会影响其他客户端的事务
watch:监控事务
multi:开启事务
exec:按照顺序对所有命令进行运行,要么成功,要么失败
布隆过滤器(解决缓存穿透的问题)
本来数据库没有的东西,去缓存里面获取没有获取,再去数据库里面获取,叫做缓存穿透
布隆过滤器:如何用小的内存处理大的数据
概率解决问题
不可能百分百阻挡
>1%
1,你有啥
2,有的向bitmap中标记
3,请求的可能被误标记
4,但是,一定概率会大量减少放行:穿透
5,而且,成本低
1、穿透了却不存在
2、client增加redis中的key,value标记
3、数据库增加了元素,
4、必须要完成元素对bloom的添加
redis作为数据库和缓存的区别
缓存数据不重要,不是全量数据
缓存应该随着访问变化(热数据)
redis作为缓存
redis里的数据怎么能顺着业务变化,只保留热数据,因为内存大小是有限的,也就是瓶颈
业务逻辑--------》key的有效期
业务运转--------》内存是有限的,随着访问变化,应该淘汰到冷数据
内存多大呢?
maxmemory
maxmemory-policy noeviction
LFU 最不经常使用淘汰算法(Least Frequently Used)。LFU是淘汰一段时间内,使用次数最少的页面。
LRU 最近最少使用淘汰算法(Least Recently Used)。LRU是淘汰最长时间没有被使用的页面。
redis的过期
1、不会随着访问延长
2、发生写,会剔除过期时间
3、倒计时,且redis不能延长
4、定时
5、业务逻辑自己补全
过期判定原理:
1、被动访问时判定
2、周期轮询判定(增量)
目的,稍微牺牲下内存,但是保住了redis性能为王
持久化
RDB:快照/副本
时点性:
save:触发前台阻塞
bgsave:fork(),创建子进程
配置文件中save这个标识,给出bgsave的规则:
1、save——阻塞,redis不对外进行服务
2、bgsave——fock cow:创建子进程,父子进程对数据的修改对方看不见,一个负责增删改,一个负责查,两个进程绑定,父进程异常退出,子进程也退出
弊端
1、不支持拉链,只有一个dump.rdb
2、丢失数据相对多一些,时点之间窗口数据容易丢失,8得到一个rdb,9点要洛一个rdb,宕机了,丢失一个小时
优点
类似java中的序列化,恢复的速度比较快
管道:
1,衔接,前一个命令的输出作为后一个命令的输入
2,管道会触发创建【子进程】
父子进程
父进程的数据,子进程可不可以看得到?
常规思想,进程是数据隔离的!
进阶思想,父进程其实可以让子进程看到数据!
linux中
export的环境变量,子进程的修改不会破坏父进程
父进程的修改也不会破坏子进程
创建子进程的速度应该是什么程序,如果父进程是redis,内存数据比如10g
1、速度
2、内存空间够不够
fork():创建子进程(系统调用)
1、速度快
2、空间小
copy on write:写时复制,创建子进程时并不复制,玩的是指针(内核机制)
创建进程变快了,根据经验,不可能子进程或者父进程把所有进程都改一遍
AOF:日志
redis的写操作记录到文件中
1、丢失数据相对少
2、redis中RDB和AOF可以同时开启,如果开启了AOF,只会用AOF恢复,4.0之后,AOF中包含RDB全量,追加记录新的写操作。
3、弊端,体量无限变大,恢复慢
日志有点如果能保住,还是可以用,设计一个方案,让AOF足够小
1、4.0以前:重写,删除抵消的命令,合并重复的命令,最终也是一个纯指定的日志文件
2、4.0以后,重写,将老的数据RDB(二进制,不可阅读)到aof文件中,完成之后提换掉原有的AOF文件,并且将增量的以指令的方式Append到AOF中,AOF是一个混合体,利用了RDB的快,利用了日志的全量
4、redis是内存数据库
写操作会触发IO,
NO:等内核满了,自动去写,不调用flush命令让数据进行写入,容易丢失数据
AWAYS:每笔数据都调用flush去写数据,特别慢
每秒:没一秒调用flush推出一下缓冲区
bgrewriteaof:对AOF文件进行重写
AOP操作:
关闭所有redis的进程
更改/etc/redis/6379.conf配置文件
/var/lib/redis/中存放的日志文件
启动输入bgsave时启动rdb模式
Redis集群方式
单机单节点单实例的问题
1、单点故障
2、容量有限
3、压力比较大
AKF
基于X轴:全量的,镜像
基于Y轴:业务,功能
基于Z轴:优先级,逻辑再拆分
通过AKF
一变多
数据一致性!!!!
所有节点阻塞直到数据全部一致
*,同步方式阻塞方式
强一致性!
破坏可用性!反问自己:为什么一变多,解决可用性
*,通过异步方式
1,容忍数据丢失一部分
主从复制设置
在从的客户端通过命令通知,5以前的命令SLAVEOF,5以后的命令REPLICAOF,自己设置自己时REPLICAOF no one:表示我自己说了算
一个redis实例想追随另外一台,追随的那一台需要清掉自己的数据
追随之后遇到情况
1、从挂
重新启动时,配置文件中重新配置追随,会同步主机的数据,不会丢失
如果重新启动时,重新设置了AOF模式,那么将会出现一点小问题
2、主挂
人为的把从机设置为主,设置另一台追随它
配置文件中
replicaof属性:表示要追随的是谁,设置自己时参数设置为no one
replica-serve-stale-data yes:是不是同步完才开始给客户端数据
repl-diskless-sync no:磁盘io到RDB文件,在通过网络io传输接收主机数据,yes:直接走网络io,不走磁盘io
repl-backlog-size 1mb :增量复制的大小
min-replicas-to-write 3:最少写几个写成功
min-replicas-max-lag 10:
sentinel哨兵
负责:
监控,提醒,自动故障迁移
配置
port 26379:配置sentinel的端口号
sentinel monitor mymaster 127.0.0.1 6381 2:配置监控的端口号,还有出现故障几票可以切换
sharding分片
代理的使用
twemproxy,
教学在github上面搜索https://hub.fastgit.org/twitter/twemproxy
查看readme.md文件有详细介绍
predixy
github上有详细介绍,直接搜索,predixy,readme.md文件中有详细介绍
cluster
redis自带软件,源码中的utils/create-cluster中有大致写好的文件和readme文件,和一个写好的脚本模板
面试常见
击穿:
redis做为缓存时,key过期时,大量的并发请求这个key,都将进去数据库里面存储数据
解决
redis是单进程的单实例的,1,get key 2.setnx,3.false sleep->1
穿透:
业务接收的是我直接不存在的数据
解决:
布隆过滤器:有一个弊端,只能增加节点,不能删除节点
雪崩:
大量的key同时失效
解决
分散过期时间