redis

cache:读缓存,是为了调节速度不一致的两个或多个不同物质的速度。例如cpu先从内存读,内存没有再读磁盘。

buffer:写缓冲,先将数据写入自己最近的地方,,例如cpu写数据会先写入内存。后续由内核写入磁盘

缓存保存位置及分层结构

用户层:浏览器DNS,应用程序DNS,操作系统DNS缓存

代理层:CDN,反向代理缓存

web层:web服务器缓存,解释器opcache

应用层:页面静态化

数据层:分布式缓存,数据库

系统层:操作系统cache

物理层:磁盘cache,raid cache

 

cache特性

自动过期  缓存数据有实效,超过时间自动删除

强制过期  源网站更新内容后CDN不会自动更新,需要强制让缓存过期

命中率  缓存的读取命中率

 

浏览器缓存过期机制

1 最后修改时间 last-modified。浏览器请求文件时,会获取last-modified和本地浏览器缓存的文件修改时间比较,如果一样,那么就会返回304,从缓存中读取内容。如果不一样,那么就会重新请求。需要向服务器发起请求才可以使用缓存

2 etag标记:是httpheader中代表资源的标签,在服务器端生成。如果有etag,下一次发送带有etag的请求事,etag没有变化将返回304。需要向服务器发起请求才可以使用缓存

3 过期失效时间expires:由服务端设置,在expires内都不会http请求,直接读取缓存。强制刷新除外。默认过期时间为30天。如果设置过期时间为1年,资源的失效是从客户端请求开始计算往后1年失效。

4 混合使用

    last-modified和expire混合使用

 etag和expire混合使用:判断expire,过期则发起http请求,然后根据etag返回200或者304

 三者混合使用:先判断expire,过期发送http请求,先判断last-modified,如果一致,再判断etag,还是一致,才能返回304

 

nosql数据库类别

临时性键值存储  memcached,redis

永久性键值存储 roma,redis

面向文档的数据库 mongob,couchdb

面向列的数据库 cassandra ,hbase

rbdms和nosql的对比

特点

  关系型数据库 nosql
特点

数据关系基于关系模型,结构化存储,完整性约束

基于二维表及其之间的联系

采用结构化的查询语言做数据读写

操作需要数据的一致性,需要事务甚至是强一致性

非结构化的存储

基于多维关系模型

具有特有的使用场景

优点

保持数据的一致性(事务处理)

可以进行join等复杂查询

通用性,技术成熟

高并发,大数据下读写能力较强

基于支持分布式,易于扩展,可伸缩

简单,弱结构化存储

缺点

数据读写必须经过sql解析,大量数据,高并发下读写性能不足

对数据读写,或修改诗句结构时需要加锁,影响并发操作

无法适应非结构化存储

扩展困难

复杂

jion等复杂操作能力弱

事务支持弱

通用性差

无完整约束复杂场景支持较差

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

redis对比memcached

支持数据的持久化:能将内存中的数据保存在磁盘中,重启redis服务或者服务器可以从备份文件中恢复数据到内层中继续使用

支持更多的数据类型:string,hash,list,set,zset

支持数据的备份:可以实现类似于数据的master-slave模式的数据备份,也支持使用快照和aof

支持更大的value数据:memcache单个key value最大只支持1mb,redis最大支持512mb,生产不建议超过2m

在redis6版本前,redis是单线程,memcache是多线程,单机情况下并发不高,但是支持分布式集群可以实现数万并发

都是基于c语言开发

 

redis典型应用场景

session共享:常见于web集群中的tomcat

缓存:数据查询,电商网站商品信息,新闻内容

计数器:访问排行榜,浏览数等和次数相关的数值统计场景

微博微信:共同好友,粉丝数,关注,点赞评论等

消息队列:elk的日志缓存

地理位置:摇一摇,附近的人,外卖等

 

编译安装redis

---------------------------------------------------------

yum -y install gcc jemalloc-devel    下载依赖

wget http://download.redis.io/releases/redis-5.0.3.tar.gz

tar xvf redis-5.0.3.tar.gz

cd redis-5.0.3/

make PREFIX=/apps/redis install    安装目录自定义

echo 'PATH=/apps/redis/bin:$PATH' > /etc/profile.d/redis.sh  

. /etc/profile.d/redis.sh

mkdir /apps/redis/{etc,log,data,run}  创建配置文件,日志,数据等

cp /app/redis-5.0.3/redis.conf  /apps/redis/etc/    将redis.conf拷贝到安装目录etc下

redis-server redis.conf   前台启动redis

 

 ------------------------------------

 可以开启redis多实例

redis-server  --port 6380

chown -R redis.redis /apps/redis/              很重要

-----------------------------------------------

解决启动时的警告

1.vim /etc/sysctl.conf

net.core.somaxconn=1024

vm.overcommit_memory=1

 

2.echo 'echo nerver' > /sys/kernel/mm/transparent_hugepage/enabled'  >> /etc/rc.d/rc.local

chmod +x /etc/rc.d/rc.local

---------------------------------------------------

编辑redis的systemd启动文件,复制yum安装的进行修改路径

 

验证redis启动

systemctl daemon-reload      systemctl enable --now redis

 

 

 

-----------------------------------------------------

多实例部署

 

 

将原来的redis.conf修改redis_6379.conf,红色为修改部分

bind 0.0.0.0
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /apps/redis/run/redis_6379.pid
loglevel notice
logfile "/apps/redis/log/redis_6379.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /apps/redis/data/
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly no
appendfilename "appendonly_6379.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes

修改完后复制成redis_6380.conf  ,redis_6381.conf。对应的systemd启动文件复制修改(改下对应的配置文件名字即可)。其他的不需要动。data,log,pid会自动生成。

 

 

 

 

 启动!!!systemctl daemon-reload           systemctl enable --now redis_6379 redis_6380 redis_6381

 

redis持久化

rdb:基于时间的快照,保留最新的一次快照文件。可能会丢失上次快照到当前没有快照的数据。当数据量非常大的时候,父进程fork出来的子进程将内容保存到rdb文件需要时间,取决于磁盘IO性能。数据量大会造成fork耗时大,服务器会在一定时间内停止处理客户端请求

实现rdb方式  save(同步)

      bgsave(异步)  --------------redis-cli   bgsave   生产使用最多,可以通过脚本执行bgsave命令生成多个备份。如下图

      自动:制定规则,自动执行

 

 

AOF:顺序添加内容到制定日志文件。默认为每秒同步一次,即保存到AOF当中。可以设置同步策略always,边同步边接受请求。由于写入采用的append模式,即使宕机也不会影响数据。如果写入一般出现系统崩溃,可以通过redis-check-aof工具解决数据一致性问题。重复操作也会记录,aof文件大于rdb,大数据量恢复速度也比rdb慢,bug多。

同时启用rdb和aof时,aof优先级高。由于aof默认是关闭的,当开启后重启服务,会导致所有数据丢失。

启动AOF:生成aof文件

redis-cli

127.0.0.1:6379> config set appendonly yes

 

 

redis数据类型

字符串string

列表list

集合set

有序集合sorted set

哈希hash

 

 

消息队列

消息队列:把要传输的数据放在队列里

功能:实现多个系统的解耦,异步,限流等

常见消息队列:kafka,rabbitmq,redis

 

队列模式

1生产者消费者模式:多个消费者同时监听一个队列,消息任务是一次性读取和处理。一个消息只能被消费一次。

2发布者订阅者模式:发布者将消息发布到指定的channel中,凡是监听这channel都会收到消息,类似广播。

     此模式常用群聊天,通知等

   publisher:发布者      subsriber:订阅者    channel:频道

 

 

redis集群与高可用

---------------------------------------------------

主从复制特点

 一个master可以有多个slave,一个slave只能有一个master,数据流是单向的,master到slave

主从复制实现

不光master要开启数据持久化,slave也要开启持久化,因为slave会有提升为master的可能,slave切换成master同步后会丢失所有数据,持久化可以恢复数据。

一旦某个slave称为一个master的slave,slave会清空自己数据,把master的数据导入,但是如果只是断开同步关系后,则不会删除自己数据。

假设a为master,b和c都是slave。a关闭持久化后,a崩溃后,自动拉起重启a后,a数据为空,b和c从a复制数据,因为a为空,所以b和c把自己数据都删了

a  192.168.89.130      master

b 192.168.89.131      slave

c 192.168.89.132     slave

为了简化过程,同一yum isntall -y redis

 

a    设置key1值v1为master

 

b设置key1值为slave1

c设置key2值为slave2

此时a,b,c均为master。配置b,c的redis.conf  -----------bind 0.0.0.0,replicaof 192.168.89.130 6379    a的redis.conf----bind 0.0.0.0

如此成功建立主从,a有两个slave,slave同步a的数据。如下图

 

 

删除主从同步,只断开与master的联系,但是不会删除自身已有的数据。---- 在slave执行replicaof no one

此时slave只读无法写入数据

  

 

 

主从搭建时常见故障现象: master_link_status:down

原因1:密码不一致

原因2:master与bind没有修改0.0.0.0,无法互相监听

 

主从复制故障恢复

slave节点故障和恢复

client指向另一个从节点即可,并及时修复故障从节点

 

 master节点故障和恢复

手动提升一个slave作为新的master,不支持自动切换。master的切换导致master_replid变化,slave之前的master_replid和当前master不一致就会引起所有slave的全量同步。

举例 a master,b和c和d都为slave。当a挂掉后,手动将b提升为master。那么b作为a的slave的master_replid和b变成master的master_replid不同,c和d都要重新指向b生成新的master_replid并且同步b的数据。

配置如下

a     systemctl stop redis

b      replicaof no one→set  key6  bbbb        bind 0.0.0.0不要忘记

c,d     replicaof <b的ip> 6379        bind 0.0.0.0不要忘记

 

实现redis的级联复制

配置依旧那么简单。还是abcd四兄弟,a作为master,b作为a的slave,作为c和d的smater。

a     啥都不需要配               bind 0.0.0.0 不要忘记

b     replicaof <a的ip> 6379        bind 0.0.0.0不要忘记

c,d    replicaof <b的ip> 6379        bind 0.0.0.0不要忘记

 

主从复制优化

全量复制过程:从服务器从主服务器同步数据,从服务器还可以有从服务器。当主服务器收到从服务器同步请求时,fork出子进程执行bgsave,将数据写入rdb中,把rdb文件给slave。然后缓冲区的内容以redis协议格式再给slave。slave先删除旧数据,然后将rdb放入内存,再加载缓冲区内容,从而完成全量同步。

增量复制过程:全量之后再次同步时,从服务器发送当前的offset位置给主服务器,让后主服务器把offset之后的数据给slave。

所说的缓冲区需要配置-----开启即可。一个是设置缓冲区大小,一个是设置slave没有同步需求,可以释放环形队列

 

避免全量复制

1 第一次全量必不可少,后续在业务低峰时全量

2节点进行ID不匹配:master重启导致runid变化,可能触发全量复制,可以利用哨兵或者集群

3 缓冲区不足:master生成的新数据大于缓冲区大小,从节点恢复和主节点连接后,会导致全量,解决方法调大缓冲区大小

避免复制风暴

1.单master复制风暴:主节点重启,所有从节点重新复制。解决思路:从节点建立从节点,master---slave---slave的slave

 2.单机器复制风暴:宕机后,大量全量复制。解决思路:多个master

优化配置

repl-diskless-sync no        不用无盘同步rdb,先保存在磁盘在发送slave

repl-diskless-sync-delay 5       diskless时复制服务器等待的延迟时间

repl-ping-slave-period 10        slave向server端发送ping的时间间隔

repl-timeout 60              主从连接超时时间

repl-disable-tcp-nodelay no     no是master立即发送同步数据,没有延迟,数据一致。yes是合并小tcp包节省带宽,会增加同步延迟,数据会不一致。

repl-backlog-size  1mb       master的写入数据缓冲区,计算公式=每秒写入大小*允许从节点最大中断时间

repl-backlog-ttl  3600        slave没有连接到master的时间,repl-backlog-size 释放。值为0,永不释放

slave-priority 100          当master故障时选择slave来进行恢复,数字越小优先级越高。如果值为0,那么不会被选择

min-replicas-to-write 1    一个master的可用slave不能少于多少个,否则master无法写入

min-slaves-max-lag 20     有多少数量的slave延迟大于多少秒是,master不接受写入

 redis哨兵(sentinel)

主从架构问题:1主从无法故障无法自动切换,用户无感知不影响业务2主从无法横向扩展的并行写入性能

redis集群实现方式:

  客户端分片:由应用决定将不同的key发送到不同redis服务器上

  代理分片:有代理决定将不同的key发送到不同redis服务器上

  redis cluster:多个master

sentinel原理

 

 

 

开始部署哨兵服务器☺----sentinel就是个特殊的redis服务器,所以一般和redis部署在一起(可以分开,配置指向redis就可以啦)。因为需要依靠redis主从,所以就用上面的主从架构

a,b,c   sed -i  's#127.0.0.1 6379 2#192.168.89.130 6379 2#g' /etc/redis-sentinel.conf

a,b,c          systemctl enable --now  redis-sentinel.service

搞定了是不是很简单,现在验证下端口(哨兵端口26379)

 

 

 

可以查看日志-----cat /var/log/redis/sentinel.log

 

 

 

测试redis master故障能够转移

a        killall redis-server

再次查看  /var/log/redis/sentinel.log

 

 

 

可以看到redis master变化了,将a的服务再起来,a变成了slave,b变成了master,c指向了b

 

 

 

 

 

 

 

 sentinel运维

1.这个在前面介绍过了,值越小优先变成master

2.redis-cli -p 26379  sentinel failover mymaster

java连接sentinel(我不会哈哈)

https://github.com/redis/jedis/blob/master/pom.xml

python连接sentinel

yum install python3 python3-redis

vim /etc/sentinel_test.py

#!/usr/bin/python3
import redis
from redis.sentinel import Sentinel

sentinel = Sentinel([('192.168.89.130',26379),('192.168.89.130',26379),('192.168.89.130',26379)],socket_timeout=1)

master = sentinel.discover_master('mymaster')
print(master)
slave = sentinel.discover_slaves('mymaster')
print(slave)
master = sentinel.master_for('mymaster',socket_timeout=1,db=0)
w_ret = master.set('name','zhangsan')

slave = sentinel.slave_for('mymaster',socket_timeout=1,db=0)
r_ret = slave.get('name')
print(r_ret)
~                     

 

 

redis cluster

sentinel虽然解决了master故障自动将slave提升为master,但是无法解决redis单机写入的瓶颈问题。

cluster特点

1.所有redis节点ping互联

2.集群中某个节点的是否失效,由集群超过半数的节点检测都失效才算真正的失效

3.客户端不需要proxy即可直接连接redis,应用程序需要配置全部的redis服务器ip

4.redis cluster把所有的redis node平均映射到0-16383个槽位上(slot),读写需要到指定的node上进行操作,相当于有多少个redis node就等于redis并发扩展了多少倍,每个redis node承担16384/N个slot

5.redis cluster月线分配16384个slot,当需要在集群写入一个key-value时,会使用key mod 16384之后的值,决定将key写入至哪个slot从而决定写入哪个node,从而解决单机瓶颈

简单架构如下

redis cluster部署有3种方式-------------------------基于5版本

1 原生命令安装    生产不适用

2  官网工具安装

3  自主研发

 --------------------------------------

重点官方工具安装

--------------6个节点 192.168.89.140-145

→1 vim /etc/redis.conf配置

bind 0.0.0.0

masterauth 123456

requirepass 123456

cluster-enabled yes   开启

cluster-config-file nodes-6379.conf   集群状态文件

cluster-require-full-coverage no

→2创建集群 每个master对应一个slave

[root@]# redis-cli -a 123456 --cluster create 192.168.89.140:6379 192.168.89.141:6379 192.168.89.142:6379 192.168.89.143:6379 192.168.89.144:6379 192.168.89.145:6379 --cluster-replicas 1

→3验证集群

 

 →4查看主从关系

 

 

 

→5验证集群写入key

 

 

 

 

 →6计算key的slot

 

 

→7故障测试 (192.168.89.140关闭redis,对应的slave节点143状态变化),192.168.89.140重启redis后两节点之间的变化

 

 

 

 集群维护

→1集群动态扩容。可以在任何节点添加比如添加146节点。配置需要和已有节点一样,不再重复讲了

[root :]redis-cli -a 123456 --cluster add-node  192.168.89.146:6379   192.168.89.141:6379

 

 ###新添加的master没有槽位,所以需要重新分配,但是注意重新分slot会清空数据,请先备份

[root :]redis-cli  -a 123456 --cluster reshard 192.168.89.141:6379        这里可以为集群的任何节点

how many slots do you want to move(from 1 to 16384)?        新分配多少slot=16384/master个数  这里就是4096

what is the receiving node ID?新的master ID          241b1730bfaba6e63171069e391ff301ef4ac078

source node #1: all      

do you want to proceed with the proposed reshard plan (yes/no)  yes

##吧新的节点147作为146的slave加入集群

redis-cli -a 123456 --cluster add-node 192.168.89.147:6379 192.168.89.141:6379 --cluster-slave --cluster-master-id 241b1730bfaba6e63171069e391ff301ef4ac078

→2集群动态缩容。首先将被删除的node上的slot迁移到其他node上,然后删除被迁移的mater必须没有数据,否则报错并强制终端

##选择将147节点的slot平均分给3个master-(140,141,142)

redis-cli -a 123456 --cluster reshard 192.168.89.147:6379  将147的1365个slot分给master141

how many slots do you want to move(from 1 to 16384)?1356

what is the receiving node ID?    9637db8db3f41e14ace33bfc74bdcd54c05ec532

do you want to proceed with the proposed reshard plan (yes/no)  yes

redis-cli -a 123456 --cluster del-node 192.168.89.146:6379 241b1730bfaba6e63171069e391ff301ef4ac078

 

posted @ 2021-09-03 00:41  好像认识你很久了  阅读(51)  评论(0)    收藏  举报