知识回顾:
redis是单机单进程的,可做缓存可做数据库,
持久化方案:RDB和AOF,如果当作缓存用RDB就够了,如果当作数据库要开启AOF;
RDB(relation-ship database)持久化:
默认redis会以一个rdb快照的形式,将一段时间内的数据持久化到硬盘,保存成一个dumpr.rdb二进制文件。
工作原理:当redis需要持久化时,redis会fork一个子进程,子进程将数据写到磁盘上临时一个RDB文件中。当子进程完成写临时文件后,将原来的RDB替换掉,这样的好处就是可以copy-on-write。
//配置redis.conf: save 900 1 save 300 10 save 60 10000 //在900秒内,如果有一个key被修改,则会发起快照保存。300秒之内,如果超过10个key被修改,则会发起快照保存。在60秒内,如果1w个key被修改,则会发起快照保存。
aof(append-only file)持久化:
默认会以一个appendonly.aof追加进硬盘。
//redis.conf默认配置: appendfsync yes appendfdync always //每次有数据修改都会写入AOF appendfsync everysec //每秒同步一次,策略为AOF的缺省策略
存在问题:1、单点故障;2、容量有限;3、压力(i/o压力、连接数压力)
解决的方式是,将单节点变为多节点:
1、读写分离
2、基于三维进行扩展AKF
微服务拆分原则:
1、AFK拆分原则;
2、前后端分离原则;
3、无状态服务
4、RestFul通讯风格
AKF拆分原则:X:全量镜像(主可发生读写,备只能读)
Y:按照不同业务,将不同数据存储到不同的redis中
Z:按照优先级,逻辑再划分
通过AFK一变多,问题:数据一致性问题。
方案:1、强一致性,所有节点阻塞直到数据全部一致;极易破坏可用性;
2、弱一致性,通过异步方式,容忍数据丢失一部分。
3、最终数据会一致,可在中间加入中间件,比如kafka
集群方式:
分布式常见的几个架构:
主备:主机死了,备机可以顶
主从(对主做HA高可用):主机后面有几个从节点。(redis用的是主从复制);
我们对主进行HA架构,用一个程序进行监控,该监控程序,为了避免单点故障,那么也必须是一个集群架构。
我们的监控设备一定是奇数台,进行过半选举,如果过半都选举故障,那么,将会跳到另一台节点。
推导:1、统计不准确,不够势力范围;问题:网络分区、脑裂
CAP原则
不能解决容量的问题,在X轴方向做集群;
哨兵
1、启动3个哨兵,进行监控
redis-server ./26379.conf --sentinel //也可以直接启动redis-sentinel
port 26379 sentinel monitor mymaster 127.0.0.1 6379 2
第二行语义:哨兵 监控 监控名 ip 端口 几票通过
需要过30秒哨兵才能生效
reids单节点容量问题解决方案
可以进行业务拆分,数据分类;到了数据不能拆分的时候,可以进行数据分片;
1、哈希取模hash+取模(弊端:模数固定,节点的拓展比较麻烦,新增一台机器必须重新取模);
2、随机random(弊端:取回数据的时候比较麻烦,需要便利)
3、一致性哈希算法(优点:的确可以分担其他节点的压力,也不会造成全局洗牌。弊端:新增系欸但会造成一小部分数据无法名中)
没有取模,client的key和node都需要进行计算,规划成一个哈希环
导致的问题:
1.可能造成击穿
2.增加复杂度,每次取离数据最近的2个物理节点
哈希环上的节点数尽可能多,可以解决数据倾斜的问题,也就是虚拟节点技术.
方案:设法取离我最近的2个物理节点
该方案更倾向于作为缓存,而不是数据库使用
客户端连接过多问题
redis的连接成本很高,对server端,引入代理proxy
在linux版本比较低时可升级一下
yum update nss //搜索安装软件 yum search xxx //安装软件 yum install xxx
安装:
git clone https://github.com/twitter/twemproxy.git //如果报错,执行:yum update nss yum install automake libtool autoreconf -fvi //如果报错,执行 wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo yum clean all yum install autoconf268.noarch -y autoreconf268 -fvi ./configure --enable-debug=full make //查看服务文件 cd scripts nutcracker.init //拷贝这个文件进/etc/init.d目录 //拷贝编译运行文件进/usr/bin目录 //拷贝conf文件夹进/etc/nutcracker目录 //进入/etc/nutcracker,修改nutcracker.yml进行配置 alpha: listen: 127.0.0.1:22121 hash: fnv1a_64 distribution: ketama auto_eject_hosts: true redis: true server_retry_timeout: 2000 server_failure_limit: 1 servers: - 127.0.0.1:6379:1 - 127.0.0.1:6380:1 //之后开启nutcracker服务,开启service服务,之后连接redis-cli进行连接22121端口 我们通过nutcracker进行get和set,我们在nutcracker不支持的命令: keys * watch k1 multi //这些命令都不支持
predixy软件,也可作为替代品
wget https://github.com/joyieldInc/predixy/releases/download/1.0.5/predixy-1.0.5-bin-amd64-linux.tar.gz
修改predixy.conf
打开Bind 127.0.0.1:7617
打开include sentinel.conf
修改26379的哨兵
port 26379 sentinel monitor ooxx 127.0.0.1 36379 2 sentinel monitor xxoo 127.0.0.1 46379 2
解决方案:使用setnx() ->相当于一把锁,设置的时候,发现设置过期,加锁,只有获得锁的人才可以访问DB,这样就能防止击穿。
逻辑
get key setnx if ok addDB else sleep go to 1
问题1:如果第一个加锁的人挂了?
可以设置过期时间
问题2:如果第一个枷锁的人没挂,但是锁超时了?
可以使用多线程,一个线程取库,一个线程监控前一个线程是否存活,更新锁时间;
穿透
解决方案:
使用布隆过滤器,不存在的数据使用bitmap进行拦截
1.使用布隆过滤器。从客户端包含布隆过滤器的算法。
2.直接redis集成布隆模块。
问题1:布隆过滤器只能查看,不能删除?
换cuckoo过滤器
雪崩:
解决方案:在失效的基础上,再加入一个时间(1-5min)
1、时效性无关的:随机过期时间
2、必须两点过期的,强依赖击穿方案,或者在业务层拦截请求,睡几秒秒然后放行
Redis做分布式锁
1、setnx
2、过期时间
3、守护线程,延长过期时间
还有redisson
zookeeper做分布式锁最方便