1 RDB 数据快照(快) AOF操作日志追加(慢)
2 同时开启AOF和RDB时恢复数据时候优先使用AOF回复因为AOF 较RDB安全
3 Redis支持主从(2.x)和集群(3.x)
4 redis 支持数据持久化,可以将内存的数据保存到磁盘中,重启时候可以再次记载原数据
5 redis 单键值支持1G的数据存储。
redis的特点
1 redis是一个高性能的K/V数据库
2 基于内存
3 数据类型呢丰富
4 持久化
5 单线程(单进程单线程模型【多路复用IO模型】)
6 订阅/发布模型(spring-session)
redis2.x主从搭建:
特性:1 主机支持读写,从机只支持读,不支持写操作
对于从机的写操作只能有主机同步来完成。
2 不支持自动故障转移
3 不支持分片<分片需要自己去做>
1 <安装redis>
1.1 首先解压redis2.6.17
1.2 到redis目录下执行make脚本编译redis
1.3 编译完成后你可以试着执行make test去执行redis的test程序去检查你的redis的安装是否存在问题,但是这是一个较慢的过程
<一般都会预执行一些src下被编译的命令>
1.4 编译完成后在src下可以看到已经被编译完成的文件,其中有一个redis-sever.sh的脚本就是启动redis的脚本
可是使用man redis-sever 查看帮助信息,也可以执行redis-server --help去查看帮助信息
一般的启动命令为 ./redis-sever /path/to/redis.conf 如果不加后面的参数 redis会使用默认的配置文件在redis的安装目录下
ps: 请注意redis的 redis.conf 文件这个文件是及其重要的。包括3.0的集群模式都是需要在这里配置的但是主从的搭建是单独靠
命令完成的
2 <启动rdis>
2.1 启动方式分为两种
第一种是前台启动
可执行 ./redis-server <端口默认是6379>
第二种是守护进程方式启动
在redis.conf中 指定daemonize yes
然后执行./redis-server redis.conf 命令 redis启动成功后会将redis的pid写入/var/run/redis.pid 文件中
你也可以通过在redis.conf中设置pidfile 属性指定进程号存放的位置
2.2 ./redis-sever [redis.conf] --port xxxx --slaveof [hostname] [portNumber] [--loglevel [debug,info,error...]]
以上是启动从redis的完整命令 --port 指定启动端口 --slaveof 指定主配置 --loglevel 指定日志等级
3 <连接redis>
3.1 连接redis ./redis-cli -h hostname -p portnum
4 <主从命令集>
4.1 redis host:port>slaveof no one 将当前的从切换为主
5 <传统分片>
5.1 以单机形式启动多台redis<主>
5.2 然后以slaveof形式为每台主启动任意个数redis[注意这里是任意个数]
5.3 客户端自己实现具体的路由算法或者直接使用Jedis中的ShardedJedis类去连接redis[客户端形式的分片]
5.4 官方分片api
JedisPoolConfig config=new JedisPoolConfig();
/*config.setMaxIdle(1000);//设置最大空闲时间
config.setMaxTotal(10);//设置最大链接数目
config.setMaxWaitMillis(1000);//设置最大等待时间
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
*/
JedisShardInfo shard1=new JedisShardInfo("localhost", 6379);
JedisShardInfo shard2=new JedisShardInfo("localhost", 6380);
List<JedisShardInfo> infos=new ArrayList<JedisShardInfo>();
infos.add(shard1);
infos.add(shard2);
ShardedJedisPool jedisPool=new ShardedJedisPool(config, infos);
ShardedJedis shardedJedis = jedisPool.getResource();
shardedJedis.set("name","zhangsan");
/*
Jedis shard = shardedJedis.getShard("key");
sherd.set("name","zhangsan");
*/
// 拿到片的信息
JedisShardInfo shardInfo = shardedJedis.getShardInfo("user100");
分片完成
rdis3.x集群
1 集群的思想
1.1 为什么redis支持海量数据的存储但是他还能基于内存 ---> cluster
1.2 传统集群是:M-S 结构 1 ~ n salver (一般来讲是 1~ 2 salver)
若是n太大会导致性能降低[同步占用IO以及cpu资源]
解决的问题:数据的单点弱化 并提高数据的冗余备份
通信方式: heart beat 发送数据包等待回复 比如ping
应用:W-R分离[分担主库的读压力]
缺点:不能自动故障转移,不能支持海量数据的存储 --解决--> 自动故障转移(选举算法)、分库分表(数据集分片的思想)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| |数据集合1| |数据集合2| |数据集合3| |----\
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |----/ 数据集合
| S | | S | | S |
| S | | S | | S |
ps:其中数据集合1为数据集合的一个片区
midleware设计 原则<读> Object data = midleware.getDataShardServer(key).负载均衡().exe(sql)
<写> midleware.getDataShardServer(key).主().exe(sql)
key为片键 可以根据唯一列的值为原始值执行算法得到值在某个范围内来找到对应的 shard sever
如果数据异构太复杂不能满足的情况下,还需要支持海量数据的存储那么我们可以使用在数据集前
搭建全文搜索引擎来存储数据与具体存储地址之间的路由规则
例如:[MD5.(data).hashcode() > 1000] : [IP:HOST]
Replication(副本集):[升级版本的 m-s] 支持自动故障转移 支持自动选举 不支持海量数据的存储
Sherd+Replication(集群):拥有多个副本集的集合 支持海量数据的存储
1.3 集群概念:一组能够协作并且能够提供海量数据的存储还能够支持自动故障转移的机器我们称之为集群
2 redis3.x集群特点
2.1 对于redis-cluster中每一个shard都要求有一个slave,所有的slave都只是负责数据的备份和请求的路由
读写只能只针对每一个从所在的主节点
这就意味着redis本地会维护一张从这台机器到各个shard的主机的路由表。
例如你通过redis-cli 连接到redis中的任何一个实例注意这里不管是否是w或是r请求,你的请求都会被路由到
该键被计算后落入的哈希槽所在的Replication的主机上。然后具体执行用户的读写操作。
注意是在你打出set 或 get 命令之后才被从定向。确保你知道这点
2.2 redis怎么做到数据的负载均衡
端口:
当redis开启集群模式时候每一个实例会开启两个tcp端口
第一个端口是用于服务客户端的第二个端口是提供给数据传输和故障检测使用的
一般情况下两个端口的差会在10000 例如6379 和16379
第二个高位端口会承担数据传输的责任并且还提供所谓的心跳故障检测
一般做法 一致性hash:
MD5(唯一key).hashcode % 节点个数 得到实际节点值
rdis的做法:
在redis集群模式中会有一个hash slot的概念 它规定一个redis集群中总共会有16384个slots
当你给redis一个key时候rdis-cluster会通过一个算法<CRC16>算出该key对应的 slot 值 [1-16384]。
hash-slot映射于一个具体的数据存储单位。这个单位就是redis-cluster存取数据是索引的的基本单位!
集群中每一个shard都会对应一部分slot值默认每一个shard对应的slot值范围为16384/shardNum
所以在这种情况下,redis只需要保证算法的散列程度达到及其高,那么数据的负载均衡将达到最平均的状态
例如集群中有有三个节点
SardA:[1,5500]
SardB: [5501,1100]
SardC: [1101,16384]
以上是负载均衡的分配方式
ps: 因为数据的操纵仅仅只是针对node,所以redis-cluster不支持multi-key的操作,可是为了兼容这类操纵
redis-cluster 提供了hash-tags操作,每个key可以拥有一个自己的hash-tags 在计算存储的slot时候有限使用key的hash-tag
其次使用key的value。所以可以为不同的key规定相同的hash-tag强制他们存储在一个slot上。
但是这种做法却干预了自己的数据存储负载均衡。<不建议>
2.3 利用redis的hash-slot的特性来做权重数据存储模型
ps:只有主节点才有资格分配到hash-slot的值因为只有主节点才会有具体存储数据的桶的概念
所以可以看出我们是可以通过对hash-slot的移动来对数据的进行转移的。
这点来至于只有对分配到slot的主节点才能拥有对数据的读写能力
所以根据以上所述我们可以在操作hash-slot来操纵具体的数据从而达到对数据在各个shard之中存储的权重的把控
2.4 利用redis的hash-slot的特性来做redis路由模型
将一个主节点中的hash-slot置空。这样会使得该主节点只会路由的功能不存储任何数据!
这样我们就做到了redis的单一节点路由的功能
2.5 redis-cluster对高可用性的保证
第一点集群可用机制
只要集群中大多数master可达且失效的Master至少有一个slave可达时,即集群为非fail状态,集群是可用的
第二点redis-cluster的replicas migration机制
这种机制可以将拥有多个slave的Master的某一个slave迁移到没有slave的master下,即slave分布相对平衡
确保每个master都有一定量的slave备份
2.6 通过Gossip协议来同步数据,就是一种算法~ 不必在意
2.7 redis-cluster 会有丢失数据的风险
当客户端刚刚提交些请求时候,master返回OK,之后一瞬间(数据还未被同步成功)变成了不可达状态(或许是网络或许是宕机)
这时slave通过选举晋升为主,当主机再次加入集群时,他将以该晋升主的从的形式被添加入集群,然后去同步该主,中的数据
这时候[这条写](是客户端连接不和不可达的主机在一台机器上时候)或是
[这个时间段的写](取决于连接池正好保留了该主节点上的客户端连接并且是在主机未宕机只是网络不可达的状态下)都丢失了。
2.8 redis3.x 集群搭建
redis3.x依赖<yum install gcc><yum install ruby><yum install rubygems><gem install redis>
redis3.x集群模式中aof模式必须开启
redis.conf配置如下:
cluster-enabled yes
cluster-config-file <fliename>
cluster-node-timeout <毫秒值>
appendonly yes
ps : 若为伪分布式还需要指定端口 port xxxx filename后可追加端口号作唯一标识
分别通过redis.conf启动每一台修改过配置的redis实例 ./redis-server redis.conf
启动后在cluster-config-file 中我们会看到响应的集群节点ID这是该实例在这个集群中的唯一标识
使用redis-trib.rb 命令来创建redis集群+副本集合
例如:
./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380
127.0.0.1:6381 127.0.0.1:6382
127.0.0.1:6383 127.0.0.1:6384
其中每一个host:port代表一个开启集群模式的redis实例 create代表创建集群
--replicas 长选项后面跟的数值代表每一个副本集所拥有的salver的个数
该命令会通知各个节点加入集群,然后会自动选择主机和创建各个主机的副本(S)
到此集群就创建成功了
3 Redis3.x 集群使用以及管理
3.1 查看集群的状态 ./redis-trib.rb check 127.0.0.1:6379
注意这里只需要指定集群中的任意一个实例即可。然后该命令会为你返回整个集群的状态
3.2 使用redis-cli去连接redis-cluster
./redis-cli -c -h hostname -p portnum
以上命令中-c代表去连接集群中的一个实例。这里-h -p 还是指定集群中的任意一个实例即可
当连接上后,你每发写或者读信息时候或许会出现一条路由提示。这是你的客户端将被路由到你所get或者set的键所在的那个副本集的主机上。
3.3 自动选举机制
当只有副本集为1时候,会采取自动晋升机制!即当主机宕机时候,从会自动晋升为主机。
当主机回复时候,会在cluster-node-timeout 时间后从新加入集群中并自动成为了在宕机后晋升为主机的从
3.4 移动或者重新分配hash-slot
./redis-trib.rb reshard 127.0.0.1:6379
hostname:port 为集群中的任意一台实例
第一步骤指定hash-slot个数
第二步骤指定to的实例
第三步骤指定from的实例
3.5 从集群中删除节点(只能删除没有hash-slot的节点)
./redis-trib.rb del-node 127.0.0.1:6379
随意连接集群中的一个实例
指定id去删除实例
3.6 添加新的节点
./redis-trib.rb add-node 127.0.0.1:6385 127.0.0.1:6379
第二个参数是集群中随意的一个实例然后
第一个参数为需要加入集群的机器
这种模式下添加后,该被添加的节点在集群中的展现形式为没有从且hash-slot为0的主节点形式
且不会参与选举的过程
./redis-trib.rb add-node --slave 127.0.0.1:6385 127.0.0.1:6379
以从的形式去添加实例到集群
这样添加进去时候会考虑到集群总那个shard少就会添加到该shard中
也可以直接指定新加入从的主
./redis-trib.rb add-node --slave --master-id '集群总主机实例的id' 127.0.0.1:6385 127.0.0.1:6379
3.7 使得从机叛变
首先连接需要执行叛变实例(从机)
./redis-cli -c -h hostname -p portnum
然后执行
cluster replicate 新主机id<在集群中的id>
这样就叛变了。
3.8 使得从机器篡位
首先连接需要执行篡位的实例(从机)
./redis-cli -c -h hostname -p portnum
然后执行
cluster failover
应用 :
当我们购置新机器然后想要将机器以主机的形式加入集群时候可以先以及群方式启动该机器
然后执行./redis-trib.rb add-node --slave --master-id '集群总主机实例的id' 127.0.0.1:6385 127.0.0.1:6379
将新机器先以从机器形式加入集群,然后带数据同步完成时候,我们将执行篡位
连接到新机器./redis-cli -c -h hostname -p portnum 然后执行cluster failover 命令
到此我们的新机器已经添加完毕了
4 java-API使用redis集群
4.1 编码
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("127.0.0.1",6379))
nodes.add(new HostAndPort("127.0.0.1",6380))
nodes.add(new HostAndPort("127.0.0.1",6381))
nodes.add(new HostAndPort("127.0.0.1",6382))
nodes.add(new HostAndPort("127.0.0.1",6383))
nodes.add(new HostAndPort("127.0.0.1",6384))
nodes.add(new HostAndPort("127.0.0.1",6385))
JedisCluster jc = new JedisCluster(nodes)
String value = js.get("user")
4.2 解释
nodes中添加的是redis-cluster中所有的节点。这是将node交给JedisCluster类去帮我们自动重试和
选择节点。 注意这里是直连,不是API层面的路由。
5 使用场景
特点:
1 内存 快
2 K-V 键值存储 结构简单
3 支持cluster
4 set、setex/setnx
1 借助过期key的特性来开发分布式缓存层
2 借助exits("key")的特性来做分布式锁 不过这个有诸多的缺点,所以后面出现了zookeeper。
3 充当数据库 那么存储的数据需要满足 一些几个特性
3.1 修改频繁
3.2 数据量级小
3.3 查询简单
3.4 弱化事务 ---> 数据的完整性和数据的安全性要求不高
3.5 数据简单
例如存储用户购物车的数据,或者存储一些日志数据。还有spark中的map函数产物的存储等
4 缓冲队列
利用list的数据模型来进行缓存回写操作。适用于秒杀等操作。
5
redis缓存架构分享
1 通用架构
1.1
1.2
1.3
7 补充知识缓存架构的演变以及一些坑的分享
redis.conf文件配置
1 为redis配置白名单
bind IP
bind IP
bind IP
....
2 配置redis启动的模式
daemonize yes 守护进程启动 后台启动时候配置pid存放的位置 pidfile <或者用配置 ps -ef | grep 'redis'>
daemonize on 前台启动
3 配置启动端口
prot xxxx
4 配置redis的log输出文件
logfile <path> | stdout[标准输出]
RDB 快照持久化配置
5 配置RDB的快照时间和频率
标准表达式save <s> <keyChangeNumber> 当多s秒内内存中有keyChangeNumber个键改变时候快照数据
当多和save表达式在一起时候根据时间顺序进行条件排队校验。依次校验
做内存快照时候默认是阻止些请求的
6 配置在RDB时候对2进制数据进行压缩
rdbcompression yes
7 配置对RDB数据进行校验
rebchecksum yes
8 配置rdb数据存储的文件
dbfilename <filename>
9 配置rdb数据存储的路径
dir <path>
主从配置
10 配置主
slaveof [hostname] [portNumber]
AOF配置<就算是最糟糕的情况下最多也只会丢1秒的写>
特性:1就算是最糟糕的情况下最多也只会丢1秒的写
2AOF和RDB同时开启,优先使用AOF
11 配置开启AOF
appendonly yes
12 配置AOF操作日志存储文件
appendfilename <filename>
13 配置AOF频率
appendfsync everysec(一秒钟内所有的操作)/always(每次写)/on(当操作系统刷内存时候)
cluster配置 <3.x特有>
14 配置集群模式开启或关闭
cluster-enabled yes
cluster-enabled no
15 配置集群存储信息的文件
cluster-config-file <fliename>
16 配置redis集群的心跳超时时间
cluster-node-timeout <毫秒值>
可配置多个
17
日志配置<不需要太关系>
数据集配置<一般走默认>