商品分类引入缓存-Redis主从复制-Redis Cluster集群

实现步骤:
1.引入Redis和Spring的整合文件和Redis的属性配置文件
2.修改redis.properties的参数配置(主要修改ip和端口号)
示例:
redis.maxTotal=50
redis.node1.ip=192.168.163.235
redis.node1.port=6379
redis.node2.ip=192.168.163.235
redis.node2.port=6380
3.修改applicationContext.xml,加入redis.properties文件
4.检查和修改applicationContext-redis.xml
5.引入RedisService到Common工程下
这个类利用Jedis提供了set( ),get( )等操做redis方法
6.改写Service层代码
Redis和Spring整合+后台商品类目缓存


代码示例:
@Service
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private RedisService rs;
private static final ObjectMapper MAPPER = new ObjectMapper();
public class ItemCatService {
//存在缓存中的商品分类key,加上ITEM_CAT主要用于标识,从而区别其余的业务key
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
//1.根据key,先从缓存里查找数据
String rsResult=rs.get(ITEM_CAT_KEY);
//2.若是没有数据,说明是首次查询,则去数据库查询
List<ItemCat> resultList=itemCatMapper.findItemCatByParentId(parentId);
//3.在返回结果以前,要把查询的结果放在缓存里,京淘中是把List<ItemCat>转换为json传放在Redis中
rs.set(ITEM_CAT_KEY, MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(rsResult)){
}
//4.从缓冲中,将json串拿到,并转化为List<ItemCat>结构传回
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
List<ItemCat> resultList=MAPPER.readValue(MAPPER.readTree(rsResult).traverse(),
return resultList;
else{
}
try {
e.printStackTrace();
} catch (Exception e) {
}
return null;
public List<ItemCat> findItemCatByParentId(Long parentId) {
}
}
7.修改ItemCat 类
由于在这个类里,有一个方法:
return isParent==1?"closed":"true";
public String getState(){
}
这个方法主要是为了知足前台的js要求,但并无对应的State字段,而ObjectMapper在作格式转化时,遇到这种状况会报错:
Unrecognized field "state" (class com.jt.manage.pojo.ItemCat)
解决办法是在ItemCat类上加上一个注解:
@JsonIgnoreProperties(ignoreUnknown=true)
@Table(name="tb_item_cat")
@SuppressWarnings(value = { "all" })
public class ItemCat extends BasePojo{
…………
分区 新分区 2 的第 2 页
…………
8.从新对项目发布,而后启动测试
分区 新分区 2 的第 3 页
环境准备:
1.准备两台虚拟机
2.关闭虚拟机的防火墙
实现步骤:
1.安装第一台redis服务器,做为Master节点(本例中主节点ip是192.168.234.131)
2.进入redis安装目录,编辑redis.conf文件
只须要配置daemonize yes便可
3.安装第二台redis服务器,做为slave节点(本例中此从节点ip是192.168.234.132)
4.进入redis安装目录,编辑redis.conf文件
配置daemonize yes
配置slaveof 主节点ip 端口号
5.启动Master节点和Salve节点的Redis服务
进入到redis安装目录
执行:./src/redis-server redis.conf
6.都启动完毕后
在Master节点执行:redis-cli
而后执行:info replication
Redis 主从配置
2016年1月1日
12:07
分区 新分区 2 的第 4 页
能够看到当前的节点为Master节点
有一个从节点
从节点的ip
7.在从节点执行:redis-cli
而后执行:info replication
能够看到当前节点为从节点
主节点的ip及端口号
若是以上信息一致,证实Redis的主从配置成功。
8.测试Redis主从数据的复制,经过Master节点设置一个key value 值,好比:
set name tony
而后经过Slave节点来get 对应的key,看是否有数据
在从节点执行:
get name
有结果,证实主从复制没有问题
分区 新分区 2 的第 5 页
注意:slave节点不能执行写操做,好比在slave节点执行set 操做,会提示:
主从复制的步骤:
一、从服务器开始连接主服务器时,会向主服务器发送一个 SYNC 命令
二、主服务接收到命令以后,执行 BGSAVE,异步的将写命令保存到一个缓冲区里面
三、主服务器执行完BGSAVE以后,就.rdb 文件(BOF的持久化文件)发送给从服务器,从服务器从该
文件恢复数据到内存中
四、主服务器还会以 Redis 命令协议的格式, 将写命令缓冲区中积累的全部内容都发送给从服务
器,从服务器经过执行命令将数据恢复到内存中
分区 新分区 2 的第 6 页
哨兵机制
Redis提供了sentinel(哨兵)机制,Redis官方推荐的高可用性(HA)解决方案,当用Redis作
Master-slave的高可用方案时,假如master宕机了,Redis自己(包括它的不少客户端)都没有实
现自动进行主备切换,而Redis-sentinel自己也是一个独立运行的进程,它能监控多个master-
slave集群,发现master宕机后能进行自动切换。
每一个sentinel会向其它sentinal、master、slave定时发送消息,以确认对方是否“活”着,若是
发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的“主观认为宕机”
Subjective Down,简称SDOWN)。
若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"完全死
亡"(即:客观上的真正down机,Objective Down,简称ODOWN),经过必定的vote算法,从
剩下的slave节点中,选一台提高为master,而后自动修改相关配置。
实现步骤
1.先完成Redis的主从配置,并确保主从环境是正确可用的
2.配置Master的哨兵环境,进入Master节点的redis安装目录,编辑sentinel.conf 文件
修改配置项:sentinel monitor mymaster 192.168.234.131 6379 1
Redis哨兵
2016年1月1日
12:07
分区 新分区 2 的第 7 页
说明:监控master节点192.168.234.131,master节点使用端口6379,最后一个数字表示投票须要
的"最少法定人数",好比有10个sentinal哨兵都在监控某一个master节点,若是须要至少6个哨兵
发现master挂掉后,才认为master真正down掉,那么这里就配置为6,最小配置1台master,1台
slave,在二个机器上都启动sentinal的状况下,哨兵数只有2个,若是一台机器物理挂掉,只剩
一个sentinal能发现该问题,因此这里配置成1。
3.配置Slave的哨兵,进入Slave节点的redis安装目录,编辑sentinel.conf 文件
修改配置项:sentinel monitor mymaster 192.168.234.131 6379 1
说明:不管是主节点仍是从节点,哨兵都是检测主节点的ip
5.启动主节点的Redis服务
6.启动从节点的Redis服务
7.启动主节点的哨兵
在redis的安装目录下,执行:
./src/redis-sentinel sentinel.conf
能够看到:
哨兵已经找到并开始检测主节点
分区 新分区 2 的第 8 页
哨兵已经找到并开始检测主节点
哨兵已找到并开始检测从节点
8.启动从节点的哨兵
在redis的安装目录下,执行:
./src/redis-sentinel sentinel.conf
9.测试,down掉Slave节点后哨兵的打印(在redis 安装目录执行:./src/redis-cli -p 6379 shutdown,
或者先进入redis-cli,再执行shutdown 也能够)
10.测试,down掉Master节点后哨兵的打印
[17569] 21 Nov 11:06:57.389 # +switch-master mymaster 192.168.234.131 6379
192.168.234.132 6379
从红线部分能够看出,master发生了迁移,等刚才停掉的master再重启后,能够观察到它将被看成
slave加入,相似如下输出:
[36444] 21 Nov 11:11:14.540 * +convert-to-slave slave 192.168.234.131 6379
192.168.234.131 6379 @ mymaster 192.168.234.132 6379
11.最后,若是想中止sentinel,可输入命令./redis-cli -p shutdown 26379
12.当引入哨兵机制后,当主从关系发生变化时,sentienl.conf里的配置文件监听的Master ip 地址
也会发生变化,这个能够本身验证一下
哨兵配置项说明:
1 port <sentinel-port> :哨兵实例运行所在的端口(默认26379)
2 sentinel down-after-milliseconds mymaster <milliseconds> : master或slave多长时间
(默认30秒)不能使用后标记为s_down状态。
3 sentinel failover-timeout <master-name> <milliseconds(默认值3分钟)>
表示若是在指定时间内,mymaster仍没活过来,则启动failover,从剩下的slave中选一个升级为
master
分区 新分区 2 的第 9 页
原理说明
1.Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另一种叫作哈希槽 (hash
slot)的方式来分配的。redis cluster 默认分配了 16384(2^14) 个slot,当咱们set一个key
时,会用CRC16算法来取模获得所属的slot,而后将这个key 分到哈希槽区间的节点上,具体
算法就是:CRC16(key) % 16384。
2.集群的最大节点数量也是 16384 个(推荐的最大节点数量为 1000 个),同理每一个主节点
能够负责处理1到16384个槽位。当16384个槽位都有主节点负责处理时,集群进入”稳定
“上线状态,能够开始处理数据命令。
3.Redis 集群会把数据存在 master 节点上,而后在这个 master 和其对应的salve 之间进行
数据同步。一个主节点能够有任意多个从节点, 这些从节点用于在主节点发生网络断线或者
节点失效时, 对主节点进行替换。
备注1:
这里之因此用CRC16算法,没有用一致性hash,是由于Redis的做者认为它的crc16(key)
mod 16384的效果已经不错了,虽然没有一致性hash灵活,但实现很简单,节点增删时处理
起来也很方便。这个算法简单归纳就是把任意长度的输入经过散列算法变换成固定长度(16
位)的输出,该输出就是散列值。
CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通讯领域中最经常使用的一种差
错校验码。目前最经常使用的是CRC16和CRC32。
备注2:
须要注意的是:必需要3个或以上的主节点,不然在建立集群时会失败,而且当存活的主节点
数小于总节点数的一半时,整个集群就没法提供服务了。
以下图,集群一共有6台机器,若是有一个master挂掉,则集群没法提供服务。
Redis集群
分区 新分区 2 的第 10 页
分区 新分区 2 的第 11 页
实现步骤
1.准备一台虚拟机,关闭防火墙以及安装好Redis
2.安装Ruby,(启动Redis集群时,会用到Ruby指令)
执行:yum install ruby
(京淘提供的虚拟机已默认装好)
3.验证是否已安装好ruby
执行:ruby -v
4.肯定Redis的集群架构
本例中搭建的是6台Redis节点,实现方式是在一台虚拟机上启动6个Redis服务进程,每一个进程至关因而一个Redis
节点(固然,也能够在6台虚拟机或物理机上搭建),最后造成的集群架构是:3主3从,每一个Redis都有一个对应的
访问端口,以下图:
5.在Redis安装目录下建立cluster目录,并在cluster目录下建立6个目录,目录名为:
7000,7001,7002,7003,7004,7005
注:这样作的目的是为了更清晰的管理,路径以及目录名是本身定的
[root@localhost redis-3.0.7]# mkdir cluster
[root@localhost cluster]# mkdir 7000 7001 7002 7003 7004 7005
6.将redis.conf配置文件拷贝到这个六个目录下,以7000目录为例:
[root@localhost cluster]# cp ../redis.conf 7000
7.逐一编辑每一个目录下的配置文件,以7000目录的配置文件为例:
Redis集群搭建
分区 新分区 2 的第 12 页
7.逐一编辑每一个目录下的配置文件,以7000目录的配置文件为例:
示例:
port 7000 //端口7000
bind 本机ip //默认ip为127.0.0.1 须要改成其余节点机器可访问的ip 不然建立集群时没法
访问对应的端口,没法建立集群
daemonize yes //redis后台运行
pidfile /home/software/redis-3.0.7/cluster/7000/redis_7000.pid //pidfile文件对应7000
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes-7000.conf //集群的配置 配置文件首次启动自动生成
appendonly yes //aof日志开启 有须要就开启,它会每次写操做都记录一条日志
注:须要将主从配置项注释掉
#slave of ……
8.将7000目录下配置好的文件拷贝到其余5个目录:
[root@localhost 7000]# cp redis.conf ../7001
[root@localhost 7000]# cp redis.conf ../7002
[root@localhost 7000]# cp redis.conf ../7003
[root@localhost 7000]# cp redis.conf ../7004
[root@localhost 7000]# cp redis.conf ../7005
9.更改每一个目录下的配置文件,以更改7001目录的配置文件为例:
[root@localhost 7001]#vim redis.conf
而后在编辑模式下执行 :%s/7000/7001/g #替换全部7000为7001
其余的目录同理。
10.启动6个Redis进程
为了后续启动方便,能够编辑shell脚本。
在cluster目录下,执行:vim start.sh
内容示例:
#!/bin/sh
redis-server 7000/redis.conf &
redis-server 7001/redis.conf &
redis-server 7002/redis.conf &
redis-server 7003/redis.conf &
redis-server 7004/redis.conf &
redis-server 7005/redis.conf &
中止脚本:
redis-cli -p 7000 shutdown
redis-cli -p 7001 shutdown
redis-cli -p 7002 shutdown
redis-cli -p 7003 shutdown
redis-cli -p 7004 shutdown
redis-cli -p 7005 shutdown
11.验证6个Redis进程是否已启动:
执行:ps -ef | grep redis
12.使6个Redis进程变成一个集群:
分区 新分区 2 的第 13 页
12.使6个Redis进程变成一个集群:
切换到Redis安装目录下的src目录下,找到:redis-trib.rb 这个文件,并将这个文件复制到 /usr/local/bin 目录下
[root@localhost src]# cp redis-trib.rb /usr/local/bin/
而后执行:
./redis-trib.rb create --replicas 1 192.168.234.231:7000 192.168.234.231:7001 192.168.234.231:7002 192.168.234.231:7003
192.168.234.231:7004 192.168.234.231:7005
上图显示:三个主三个从
13.执行:redis-cli -h 192.168.234.231 -c -p 7000
14.执行测试:
好比进入7002节点,设置一对k,v 会发现k,v会被自动分配到7001节点
分区 新分区 2 的第 14 页
备注:如何查看某个redis是不是主仍是从
在redis命令行内,执行:info replication
分区 新分区 2 的第 15 页
实现步骤:
1.引入Jedis的相关依赖
2.引入Redis的属性配置文件
4.引入Redis集群整合的加载工具类
>RedisCluster.java
拷贝到jt-common工程下的util包下
5.引入Redis集群和Spring的整合文件
6.改写ItemCatService代码:
代码示意:
@Service
public class ItemCatServiceImpl implements ItemCatService {
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private JedisCluster rsCluster;
private static final ObjectMapper MAPPER=new ObjectMapper();
@Override
ItemCat itemCat = new ItemCat();
itemCat.setParentId(parentId);
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
String jsonResult=rsCluster.get(ITEM_CAT_KEY);
List<ItemCat> resultList=itemCatMapper.select(itemCat);
rsCluster.set(ITEM_CAT_KEY,MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(jsonResult)){
return MAPPER.readValue(MAPPER.readTree(jsonResult).traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
}else{
}
try {
return itemCatMapper.select(itemCat);
} catch (Exception e) {
}
public List<ItemCat> findItemCatList(Long parentId) {
}
Redis集群和Spring整合
分区 新分区 2 的第 16 页
}
分区 新分区 2 的第 17 页
Redis缓存数据的持久化
redis自身支持两种持久化方式RDB和AOF
一、RDB是定时对数据库内存作快照的方式备份整个内存数据库,这种方式,在redis或者服务
器故障的时候有可能会丢失大量数据,可是这种方式是主进程fork一个子进程来执行,不影响
到主进程的效率,也不会阻塞,同时保存数据集的完整性,若是对数据丢失能容忍一个小时左
右的数据,能够采用这种方式,性能高。
二、AOF是将redis全部写的操做做为日志存在AOF文件中,采用追加的方式,一般能够设置no:
不作aof追加,always,每次写操做都作一次追加aof文件,everysec:每秒钟追加一次,其中
always不会丢失任何数据,可是会耗不少性能,其中everysec是推荐使用的,其速度也和rdb
相差无几
若是每隔一段时间进行数据持久化,咱们叫“半持久化”。
若是每次操做都进行数据持久化,咱们叫“全持久化”。
但最多见的配置,就是关闭AOF,使用RDB方式作持久化。
RDB持久化默认生成的文件名为dump.rdb,这个能够经过配置文件配置。
Redis没有专门的RDB文件载入命令,只要Redis服务器开启,就会检测RDB文件是否存在,
就会自动载入RDB文件,
注意:若是服务器开启了AOF持久化功能,服务器会优先使用AOF文件来还原数据库状态,
只有在AOF持久化功能关闭的时候,才会使用RDB文件来还原数据库状态。
RDB方式能够自动保存,也能够能够经过手动执行,save命令和bgsave命令
注:利用save命令执行持久化操做时,服务器是被阻塞的,此时redis不能对外提供服务。
bgsave命令执行持久化操做时,服务器是不会被阻塞的,由于是单独启动一个线程来处理
的,建议使用这种方式作数据持久化
Redis.conf配置文件里,有一项配置是和RDB持久相关的参数
save 900 1
save 300 10
save 60 10000
以上表示的意思是,
900秒以内对服务进行了至少一次修改
300秒以内服务器进行了至少10次修改
60秒以内对服务器进行了至少10000次修改。
这些条件知足其中的任意一个bgsave命令就会自动执行。
Redis 数据持久化
2016年1月5日
16:19
分区 新分区 2 的第 18 页
1. Redis默认不是以守护进程的方式运行,能够经过该配置项修改,使用yes启用守护进程
daemonize no
2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,能够经过
pidfile指定
pidfile /var/run/redis.pid
3. 指定Redis监听端口,默认端口为6379,redis做者说由于6379在手机按键上MERZ对应的号
码,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
4. 绑定的主机地址
bind 127.0.0.1
5.当客户端闲置多长时间后关闭链接,若是指定为0,表示关闭该功能
timeout 300
6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为
verbose
loglevel verbose
7. 日志记录方式,默认为标准输出,若是配置Redis为守护进程方式运行,而这里又配置为日
志记录方式为标准输出,则日志将会发送给/dev/null
logfile stdout
8. 设置数据库的数量,默认数据库为0,可使用SELECT <dbid>命令在链接上指定数据库id
databases 16
Redis经常使用参数设置
分区 新分区 2 的第 19 页
databases 16
9. 指定在多长时间内,有多少次更新操做,就将数据同步到数据文件,能够多个条件配合
save <seconds> <changes>
Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个
更改。
10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,若是为了节省
CPU时间,能够关闭该选项,但会致使数据库文件变的巨大
rdbcompression yes
11. 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
12. 指定本地数据库存放目录
dir ./
13. 设置当本机为slave服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从
master进行数据同步
slaveof <masterip> <masterport>
14. 设置同一时间最大客户端链接数,默认无限制,Redis能够同时打开的客户端链接数为Redis
进程能够打开的最大文件描述符数,若是设置maxclients 0,表示不做限制。当客户端链接数
分区 新分区 2 的第 20 页
进程能够打开的最大文件描述符数,若是设置maxclients 0,表示不做限制。当客户端链接数
到达限制时,Redis会关闭新的链接并向客户端返回max number of clients reached错误信息
maxclients 128
15. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis
会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将没法再
进行写入操做,但仍然能够进行读取操做。Redis新的vm机制,会把Key存放内存,Value会存
放在swap区
maxmemory <bytes>
16. 指定是否在每次更新操做后进行日志记录,Redis在默认状况下是异步的把数据写入磁盘,
若是不开启,可能会在断电时致使一段时间内的数据丢失。由于redis自己同步数据文件是按
上面save条件来同步的,因此有的数据会在一段时间内只存在于内存中。默认为no
appendonly no
17. 指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
18. 指定更新日志条件,共有3个可选值:
no:表示等操做系统进行数据缓存同步到磁盘(快)
always:表示每次更新操做后手动调用fsync()将数据写到磁盘(慢,安全)
everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
19. 指定是否启用虚拟内存机制,默认值为no,不开启。
若是开启,则Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出
到内存中
vm-enabled no
分区 新分区 2 的第 21 页
vm-enabled no
20. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
21. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes
22.rdbchecksum no
检查RDB数据的正确性,会牺牲10%的性能,故建议关闭.
=============================================================
redis状态与性能监控
一、redis-benchmark
redis基准信息,redis服务器性能检测
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
100个并发链接,100000个请求,检测host为localhost 端口为6379的redis服务器性能
分区 新分区 2 的第 22 页
Redis 和 Memcache 都是基于内存的数据存储系统,Redis的做者Salvatore Sanfilippo曾经对这两
种基于内存的数据存储系统进行过比较:
Redis支持服务器端的数据操做:Redis相比Memcached来讲,拥有更多的数据结构和并支持更
丰富的数据操做,一般在Memcached里,你须要将数据拿到客户端来进行相似的修改再set回
去。这大大增长了网络IO的次数和数据体积。在Redis中,这些复杂的操做一般和通常的
GET/SET同样高效。因此,若是须要缓存可以支持更复杂的结构和操做,那么Redis会是不错的
选择。
内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而若是
Redis采用hash结构来作key-value存储,因为其组合式的压缩,其内存利用率会高于
Memcached。
性能对比:因为Redis只使用单核,而Memcached可使用多核,因此平均每个核上Redis在
存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于
Redis,虽然Redis最近也在存储大数据的性能上进行优化,可是比起Memcached,仍是稍有逊
色。
一、数据类型支持不一样
与Memcached仅支持简单的key-value结构的数据记录不一样,Redis支持的数据类型要丰富
得多。最为经常使用的数据类型主要由五种:String、Hash、List、Set和Sorted Set
二、内存管理机制不一样
在Redis中,并非全部的数据都一直存储在内存中的。这是和Memcached相比一个最大的
区别。当物理内存用完时,Redis能够将一些好久没用到的value交换到磁盘,可是Redis会缓
存全部的key的信息。
这种特性使得Redis能够保持超过其机器自己内存大小的数据。固然,机器自己的内存必需要
可以保持全部的key,毕竟这些数据是不会进行swap操做的。
对于像Redis和Memcached这种基于内存的数据库系统来讲,内存管理的效率高低是影响系
统性能的关键因素。传统C语言中的malloc/free函数是最经常使用的分配和释放内存的方法,但
是这种方法存在着很大的缺陷:首先,对于开发人员来讲不匹配的malloc和free容易形成内
存泄露;其次频繁调用会形成大量内存碎片没法回收从新利用,下降内存利用率;最后做为系
Redis和Memcached的对比
分区 新分区 2 的第 23 页
存泄露;其次频繁调用会形成大量内存碎片没法回收从新利用,下降内存利用率;最后做为系
统调用,其系统开销远远大于通常函数调用。因此,为了提升内存的管理效率,高效的内存管
理方案都不会直接使用malloc/free调用。Redis和Memcached均使用了自身设计的内存管理
机制,可是实现方法存在很大的差别,下面将会对二者的内存管理机制分别进行介绍。
Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,
将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以彻底解决内存碎
片问题。
当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的
Slab Class,而后经过查询Memcached保存着的该Slab Class内空闲Chunk的列表就能够找
到一个可用于存储数据的Chunk。当一条数据库过时或者丢弃时,该记录所占用的Chunk就
能够回收,从新添加到空闲列表中。
Redis的内存管理主要采用的是包装的mallc/free,相较于Memcached的内存管理方法来
说,要简单不少。
3.数据持久化支持
Redis虽然是基于内存的存储系统,可是它自己是支持内存数据的持久化的,并且提供两种主
要的持久化策略:RDB快照和AOF日志。而memcached是不支持数据持久化操做的。
四、集群管理的不一样
Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,可是全内存毕竟才是
其高性能的本质。做为基于内存的存储系统来讲,机器物理内存的大小就是系统可以容纳的最
大数据量。若是须要处理的数据量超过了单台机器的物理内存大小,就须要构建分布式集群来
扩展存储能力。
Memcached自己并不支持分布式,所以只能在客户端经过像一致性哈希这样的分布式算法来
实现Memcached的分布式存储。当客户端向Memcached集群发送数据以前,首先会经过内
置的分布式算法计算出该条数据的目标节点,而后数据会直接发送到该节点上存储。但客户端
查询数据时,一样要计算出查询数据所在的节点,而后直接向该节点发送查询请求以获取数
据。
分区 新分区 2 的第 24 页
相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式
存储。最新版本的Redis已经支持了分布式存储功能。Redis Cluster是一个实现了分布式且允
许单点故障的Redis高级版本,它没有中心节点,具备线性可伸缩的功能。在数据的放置策略
上,Redis Cluster使用的分布式算法也很简单:crc16( key ) % HASH_SLOTS_NUMBER。
为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。当
Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。
分区 新分区 2 的第 25 页
什么是redis?
Redis 是一个基于内存的高性能key-value数据库
Reids的特色
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库通通加载在内
存当中进行操做,按期经过异步操做把数据库数据flush到硬盘上进行保存。由于是纯内存操
做,Redis的性能很是出色,每秒能够处理超过10万次读写操做,是已知性能最快的Key-Value
DB。
Redis的出色之处不只仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的
最大限制是1GB,不像memcached只能保存1MB的数据,所以Redis能够用来实现不少有用的功
能,比方说用他的List来作FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set
能够作高性能的tag系统等等。另外Redis也能够对存入的Key-Value设置expire时间,所以也可
以被看成一 个功能增强版的memcached来用。
Redis的主要缺点是数据库容量受到物理内存的限制,不能用做海量数据的高性能读写,所以
Redis适合的场景主要局限在较小数据量的高性能操做和运算上。
Redis支持的数据类型
Redis经过Key-Value的单值不一样类型来区分, 如下是支持的类型:
String
Lists
Set 求交集、并集
Sorted Set
hashes
为何redis须要把全部数据放到内存中?
Redis为了达到最快的读写速度将数据都读到内存中,并经过异步的方式将数据写入磁盘。所
以redis具备快速和数据持久化的特征。若是不将数据放在内存中,磁盘I/O速度为严重影响
redis的性能。在内存愈来愈便宜的今天,redis将会愈来愈受欢迎。
若是设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。
Redis总结
分区 新分区 2 的第 26 页
Redis是单进程单线程的
redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
虚拟内存
当你的key很小而value很大时,使用VM的效果会比较好.由于这样节约的内存比较大.
当你的key不小时,能够考虑使用一些很是方法将很大的key变成很大的value,好比你能够考虑将
key,value组合成一个新的value.
vm-max-threads这个参数,能够设置访问swap文件的线程数,设置最好不要超过机器的核数,若是
设置为0,那么全部对swap文件的操做都是串行的.可能会形成比较长时间的延迟,可是对数据完
整性有很好的保证.
本身测试的时候发现用虚拟内存性能也不错。若是数据量很大,能够考虑分布式或者其余数据

分布式
redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到
master。Slave启动时会链接master来同步数据。
这是一个典型的分布式读写分离模型。咱们能够利用master来插入数据,slave提供检索服务。
这样能够有效减小单个机器的并发访问数量
数据分片模型
为了解决读写分离模型的缺陷,能够将数据分片模型应用进来。
能够将每一个节点当作都是独立的master,而后经过业务实现数据分片。
结合上面两种模型,能够将每一个master设计成由一个master和多个slave组成的模型。
Redis的回收策略
volatile-lru:从已设置过时时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘

分区 新分区 2 的第 27 页
volatile-ttl:从已设置过时时间的数据集(server.db[i].expires)中挑选将要过时的数据淘汰
volatile-random:从已设置过时时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
使用Redis有哪些好处?
(1) 速度快,由于数据存在内存中,相似于HashMap,HashMap的优点就是查找和操做的时间
复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操做都是原子性,所谓的原子性就是对数据的更改要么所有执行,要么所有不
执行
(4) 丰富的特性:可用于缓存,消息,按key设置过时时间,过时后将会自动删除
redis相比memcached有哪些优点?
(1) memcached全部的值均是简单的字符串,redis做为其替代者,支持更为丰富的数据类型
(2) redis的速度比memcached快不少
(3) redis能够持久化其数据
redis常见性能问题和解决方案:
(1) Master最好不要作任何持久化工做,如RDB内存快照和AOF日志文件,可让它的slave来
作持久化工做。
(2) 若是数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
分区 新分区 2 的第 28 页
(3) 为了主从复制的速度和链接的稳定性,Master和Slave最好在同一个局域网内
(4) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <-
Slave3...
这样的结构方便解决单点故障问题,实现Slave对Master的替换。若是Master挂了,能够马上启
用Slave1作Master,其余不变。
MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据
都是热点数据
相关知识:redis 内存数据集大小上升到必定大小的时候,就会施行数据淘汰策略。redis 提供
6种数据淘汰策略
Memcache与Redis的区别都有哪些?
Redis 常见的性能问题都有哪些?如何解决?
1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工做,当快照比较大时对
性能影响是很是大的,会间断性暂停服务,因此Master最好不要写内存快照。
2).Master AOF持久化,若是不重写AOF文件,这个持久化方式对性能的影响是最小的,可是
AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要作任何持
久化工做,包括内存快照和AOF日志文件,特别是不要启用内存快照作持久化,若是数据比较关
键,某个Slave开启AOF备份数据,策略为每秒同步一次。
3).Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导
致服务load太高,出现短暂服务暂停现象。
4). Redis主从复制的性能问题,为了主从复制的速度和链接的稳定性,Slave和Master最好在同
一个局域网内
redis 最适合的场景
分区 新分区 2 的第 29 页
redis 最适合的场景
Redis最适合全部数据in-momory的场景
分区 新分区 2 的第 30 页
实现步骤:
1.引入Redis和Spring的整合文件和Redis的属性配置文件
2.修改redis.properties的参数配置(主要修改ip和端口号)
示例:
redis.maxTotal=50
redis.node1.ip=192.168.163.235
redis.node1.port=6379
redis.node2.ip=192.168.163.235
redis.node2.port=6380
3.修改applicationContext.xml,加入redis.properties文件
4.检查和修改applicationContext-redis.xml
5.引入RedisService到Common工程下
这个类利用Jedis提供了set( ),get( )等操做redis方法
6.改写Service层代码
Redis和Spring整合+后台商品类目缓存
2017年9月24日
19:05
分区 新分区 2 的第 1 页
代码示例:
@Service
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private RedisService rs;
private static final ObjectMapper MAPPER = new ObjectMapper();
public class ItemCatService {
//存在缓存中的商品分类key,加上ITEM_CAT主要用于标识,从而区别其余的业务key
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
//1.根据key,先从缓存里查找数据
String rsResult=rs.get(ITEM_CAT_KEY);
//2.若是没有数据,说明是首次查询,则去数据库查询
List<ItemCat> resultList=itemCatMapper.findItemCatByParentId(parentId);
//3.在返回结果以前,要把查询的结果放在缓存里,京淘中是把List<ItemCat>转换为json传放在Redis中
rs.set(ITEM_CAT_KEY, MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(rsResult)){
}
//4.从缓冲中,将json串拿到,并转化为List<ItemCat>结构传回
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
List<ItemCat> resultList=MAPPER.readValue(MAPPER.readTree(rsResult).traverse(),
return resultList;
else{
}
try {
e.printStackTrace();
} catch (Exception e) {
}
return null;
public List<ItemCat> findItemCatByParentId(Long parentId) {
}
}
7.修改ItemCat 类
由于在这个类里,有一个方法:
return isParent==1?"closed":"true";
public String getState(){
}
这个方法主要是为了知足前台的js要求,但并无对应的State字段,而ObjectMapper在作格式转化时,遇到这种状况会报错:
Unrecognized field "state" (class com.jt.manage.pojo.ItemCat)
解决办法是在ItemCat类上加上一个注解:
@JsonIgnoreProperties(ignoreUnknown=true)
@Table(name="tb_item_cat")
@SuppressWarnings(value = { "all" })
public class ItemCat extends BasePojo{
…………
分区 新分区 2 的第 2 页
…………
8.从新对项目发布,而后启动测试
分区 新分区 2 的第 3 页
环境准备:
1.准备两台虚拟机
2.关闭虚拟机的防火墙
实现步骤:
1.安装第一台redis服务器,做为Master节点(本例中主节点ip是192.168.234.131)
2.进入redis安装目录,编辑redis.conf文件
只须要配置daemonize yes便可
3.安装第二台redis服务器,做为slave节点(本例中此从节点ip是192.168.234.132)
4.进入redis安装目录,编辑redis.conf文件
配置daemonize yes
配置slaveof 主节点ip 端口号
5.启动Master节点和Salve节点的Redis服务
进入到redis安装目录
执行:./src/redis-server redis.conf
6.都启动完毕后
在Master节点执行:redis-cli
而后执行:info replication
Redis 主从配置
2016年1月1日
12:07
分区 新分区 2 的第 4 页
能够看到当前的节点为Master节点
有一个从节点
从节点的ip
7.在从节点执行:redis-cli
而后执行:info replication
能够看到当前节点为从节点
主节点的ip及端口号
若是以上信息一致,证实Redis的主从配置成功。
8.测试Redis主从数据的复制,经过Master节点设置一个key value 值,好比:
set name tony
而后经过Slave节点来get 对应的key,看是否有数据
在从节点执行:
get name
有结果,证实主从复制没有问题
分区 新分区 2 的第 5 页
注意:slave节点不能执行写操做,好比在slave节点执行set 操做,会提示:
主从复制的步骤:
一、从服务器开始连接主服务器时,会向主服务器发送一个 SYNC 命令
二、主服务接收到命令以后,执行 BGSAVE,异步的将写命令保存到一个缓冲区里面
三、主服务器执行完BGSAVE以后,就.rdb 文件(BOF的持久化文件)发送给从服务器,从服务器从该
文件恢复数据到内存中
四、主服务器还会以 Redis 命令协议的格式, 将写命令缓冲区中积累的全部内容都发送给从服务
器,从服务器经过执行命令将数据恢复到内存中
分区 新分区 2 的第 6 页
哨兵机制
Redis提供了sentinel(哨兵)机制,Redis官方推荐的高可用性(HA)解决方案,当用Redis作
Master-slave的高可用方案时,假如master宕机了,Redis自己(包括它的不少客户端)都没有实
现自动进行主备切换,而Redis-sentinel自己也是一个独立运行的进程,它能监控多个master-
slave集群,发现master宕机后能进行自动切换。
每一个sentinel会向其它sentinal、master、slave定时发送消息,以确认对方是否“活”着,若是
发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的“主观认为宕机”
Subjective Down,简称SDOWN)。
若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"完全死
亡"(即:客观上的真正down机,Objective Down,简称ODOWN),经过必定的vote算法,从
剩下的slave节点中,选一台提高为master,而后自动修改相关配置。
实现步骤
1.先完成Redis的主从配置,并确保主从环境是正确可用的
2.配置Master的哨兵环境,进入Master节点的redis安装目录,编辑sentinel.conf 文件
修改配置项:sentinel monitor mymaster 192.168.234.131 6379 1
Redis哨兵
2016年1月1日
12:07
分区 新分区 2 的第 7 页
说明:监控master节点192.168.234.131,master节点使用端口6379,最后一个数字表示投票须要
的"最少法定人数",好比有10个sentinal哨兵都在监控某一个master节点,若是须要至少6个哨兵
发现master挂掉后,才认为master真正down掉,那么这里就配置为6,最小配置1台master,1台
slave,在二个机器上都启动sentinal的状况下,哨兵数只有2个,若是一台机器物理挂掉,只剩
一个sentinal能发现该问题,因此这里配置成1。
3.配置Slave的哨兵,进入Slave节点的redis安装目录,编辑sentinel.conf 文件
修改配置项:sentinel monitor mymaster 192.168.234.131 6379 1
说明:不管是主节点仍是从节点,哨兵都是检测主节点的ip
5.启动主节点的Redis服务
6.启动从节点的Redis服务
7.启动主节点的哨兵
在redis的安装目录下,执行:
./src/redis-sentinel sentinel.conf
能够看到:
哨兵已经找到并开始检测主节点
分区 新分区 2 的第 8 页
哨兵已经找到并开始检测主节点
哨兵已找到并开始检测从节点
8.启动从节点的哨兵
在redis的安装目录下,执行:
./src/redis-sentinel sentinel.conf
9.测试,down掉Slave节点后哨兵的打印(在redis 安装目录执行:./src/redis-cli -p 6379 shutdown,
或者先进入redis-cli,再执行shutdown 也能够)
10.测试,down掉Master节点后哨兵的打印
[17569] 21 Nov 11:06:57.389 # +switch-master mymaster 192.168.234.131 6379
192.168.234.132 6379
从红线部分能够看出,master发生了迁移,等刚才停掉的master再重启后,能够观察到它将被看成
slave加入,相似如下输出:
[36444] 21 Nov 11:11:14.540 * +convert-to-slave slave 192.168.234.131 6379
192.168.234.131 6379 @ mymaster 192.168.234.132 6379
11.最后,若是想中止sentinel,可输入命令./redis-cli -p shutdown 26379
12.当引入哨兵机制后,当主从关系发生变化时,sentienl.conf里的配置文件监听的Master ip 地址
也会发生变化,这个能够本身验证一下
哨兵配置项说明:
1 port <sentinel-port> :哨兵实例运行所在的端口(默认26379)
2 sentinel down-after-milliseconds mymaster <milliseconds> : master或slave多长时间
(默认30秒)不能使用后标记为s_down状态。
3 sentinel failover-timeout <master-name> <milliseconds(默认值3分钟)>
表示若是在指定时间内,mymaster仍没活过来,则启动failover,从剩下的slave中选一个升级为
master
分区 新分区 2 的第 9 页
原理说明
1.Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另一种叫作哈希槽 (hash
slot)的方式来分配的。redis cluster 默认分配了 16384(2^14) 个slot,当咱们set一个key
时,会用CRC16算法来取模获得所属的slot,而后将这个key 分到哈希槽区间的节点上,具体
算法就是:CRC16(key) % 16384。
2.集群的最大节点数量也是 16384 个(推荐的最大节点数量为 1000 个),同理每一个主节点
能够负责处理1到16384个槽位。当16384个槽位都有主节点负责处理时,集群进入”稳定
“上线状态,能够开始处理数据命令。
3.Redis 集群会把数据存在 master 节点上,而后在这个 master 和其对应的salve 之间进行
数据同步。一个主节点能够有任意多个从节点, 这些从节点用于在主节点发生网络断线或者
节点失效时, 对主节点进行替换。
备注1:
这里之因此用CRC16算法,没有用一致性hash,是由于Redis的做者认为它的crc16(key)
mod 16384的效果已经不错了,虽然没有一致性hash灵活,但实现很简单,节点增删时处理
起来也很方便。这个算法简单归纳就是把任意长度的输入经过散列算法变换成固定长度(16
位)的输出,该输出就是散列值。
CRC即循环冗余校验码(Cyclic Redundancy Check):是数据通讯领域中最经常使用的一种差
错校验码。目前最经常使用的是CRC16和CRC32。
备注2:
须要注意的是:必需要3个或以上的主节点,不然在建立集群时会失败,而且当存活的主节点
数小于总节点数的一半时,整个集群就没法提供服务了。
以下图,集群一共有6台机器,若是有一个master挂掉,则集群没法提供服务。
Redis集群
分区 新分区 2 的第 10 页
分区 新分区 2 的第 11 页
实现步骤
1.准备一台虚拟机,关闭防火墙以及安装好Redis
2.安装Ruby,(启动Redis集群时,会用到Ruby指令)
执行:yum install ruby
(京淘提供的虚拟机已默认装好)
3.验证是否已安装好ruby
执行:ruby -v
4.肯定Redis的集群架构
本例中搭建的是6台Redis节点,实现方式是在一台虚拟机上启动6个Redis服务进程,每一个进程至关因而一个Redis
节点(固然,也能够在6台虚拟机或物理机上搭建),最后造成的集群架构是:3主3从,每一个Redis都有一个对应的
访问端口,以下图:
5.在Redis安装目录下建立cluster目录,并在cluster目录下建立6个目录,目录名为:
7000,7001,7002,7003,7004,7005
注:这样作的目的是为了更清晰的管理,路径以及目录名是本身定的
[root@localhost redis-3.0.7]# mkdir cluster
[root@localhost cluster]# mkdir 7000 7001 7002 7003 7004 7005
6.将redis.conf配置文件拷贝到这个六个目录下,以7000目录为例:
[root@localhost cluster]# cp ../redis.conf 7000
7.逐一编辑每一个目录下的配置文件,以7000目录的配置文件为例:
Redis集群搭建
分区 新分区 2 的第 12 页
7.逐一编辑每一个目录下的配置文件,以7000目录的配置文件为例:
示例:
port 7000 //端口7000
bind 本机ip //默认ip为127.0.0.1 须要改成其余节点机器可访问的ip 不然建立集群时没法
访问对应的端口,没法建立集群
daemonize yes //redis后台运行
pidfile /home/software/redis-3.0.7/cluster/7000/redis_7000.pid //pidfile文件对应7000
cluster-enabled yes //开启集群 把注释#去掉
cluster-config-file nodes-7000.conf //集群的配置 配置文件首次启动自动生成
appendonly yes //aof日志开启 有须要就开启,它会每次写操做都记录一条日志
注:须要将主从配置项注释掉
#slave of ……
8.将7000目录下配置好的文件拷贝到其余5个目录:
[root@localhost 7000]# cp redis.conf ../7001
[root@localhost 7000]# cp redis.conf ../7002
[root@localhost 7000]# cp redis.conf ../7003
[root@localhost 7000]# cp redis.conf ../7004
[root@localhost 7000]# cp redis.conf ../7005
9.更改每一个目录下的配置文件,以更改7001目录的配置文件为例:
[root@localhost 7001]#vim redis.conf
而后在编辑模式下执行 :%s/7000/7001/g #替换全部7000为7001
其余的目录同理。
10.启动6个Redis进程
为了后续启动方便,能够编辑shell脚本。
在cluster目录下,执行:vim start.sh
内容示例:
#!/bin/sh
redis-server 7000/redis.conf &
redis-server 7001/redis.conf &
redis-server 7002/redis.conf &
redis-server 7003/redis.conf &
redis-server 7004/redis.conf &
redis-server 7005/redis.conf &
中止脚本:
redis-cli -p 7000 shutdown
redis-cli -p 7001 shutdown
redis-cli -p 7002 shutdown
redis-cli -p 7003 shutdown
redis-cli -p 7004 shutdown
redis-cli -p 7005 shutdown
11.验证6个Redis进程是否已启动:
执行:ps -ef | grep redis
12.使6个Redis进程变成一个集群:
分区 新分区 2 的第 13 页
12.使6个Redis进程变成一个集群:
切换到Redis安装目录下的src目录下,找到:redis-trib.rb 这个文件,并将这个文件复制到 /usr/local/bin 目录下
[root@localhost src]# cp redis-trib.rb /usr/local/bin/
而后执行:
./redis-trib.rb create --replicas 1 192.168.234.231:7000 192.168.234.231:7001 192.168.234.231:7002 192.168.234.231:7003
192.168.234.231:7004 192.168.234.231:7005
上图显示:三个主三个从
13.执行:redis-cli -h 192.168.234.231 -c -p 7000
14.执行测试:
好比进入7002节点,设置一对k,v 会发现k,v会被自动分配到7001节点
分区 新分区 2 的第 14 页
备注:如何查看某个redis是不是主仍是从
在redis命令行内,执行:info replication
分区 新分区 2 的第 15 页
实现步骤:
1.引入Jedis的相关依赖
2.引入Redis的属性配置文件
4.引入Redis集群整合的加载工具类
>RedisCluster.java
拷贝到jt-common工程下的util包下
5.引入Redis集群和Spring的整合文件
6.改写ItemCatService代码:
代码示意:
@Service
public class ItemCatServiceImpl implements ItemCatService {
@Autowired
private ItemCatMapper itemCatMapper;
@Autowired
private JedisCluster rsCluster;
private static final ObjectMapper MAPPER=new ObjectMapper();
@Override
ItemCat itemCat = new ItemCat();
itemCat.setParentId(parentId);
String ITEM_CAT_KEY="ITEM_CAT_"+parentId;
String jsonResult=rsCluster.get(ITEM_CAT_KEY);
List<ItemCat> resultList=itemCatMapper.select(itemCat);
rsCluster.set(ITEM_CAT_KEY,MAPPER.writeValueAsString(resultList));
return resultList;
if(StringUtils.isNullOrEmpty(jsonResult)){
return MAPPER.readValue(MAPPER.readTree(jsonResult).traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class,ItemCat.class));
}else{
}
try {
return itemCatMapper.select(itemCat);
} catch (Exception e) {
}
public List<ItemCat> findItemCatList(Long parentId) {
}
Redis集群和Spring整合
分区 新分区 2 的第 16 页
}
分区 新分区 2 的第 17 页
Redis缓存数据的持久化
redis自身支持两种持久化方式RDB和AOF
一、RDB是定时对数据库内存作快照的方式备份整个内存数据库,这种方式,在redis或者服务
器故障的时候有可能会丢失大量数据,可是这种方式是主进程fork一个子进程来执行,不影响
到主进程的效率,也不会阻塞,同时保存数据集的完整性,若是对数据丢失能容忍一个小时左
右的数据,能够采用这种方式,性能高。
二、AOF是将redis全部写的操做做为日志存在AOF文件中,采用追加的方式,一般能够设置no:
不作aof追加,always,每次写操做都作一次追加aof文件,everysec:每秒钟追加一次,其中
always不会丢失任何数据,可是会耗不少性能,其中everysec是推荐使用的,其速度也和rdb
相差无几
若是每隔一段时间进行数据持久化,咱们叫“半持久化”。
若是每次操做都进行数据持久化,咱们叫“全持久化”。
但最多见的配置,就是关闭AOF,使用RDB方式作持久化。
RDB持久化默认生成的文件名为dump.rdb,这个能够经过配置文件配置。
Redis没有专门的RDB文件载入命令,只要Redis服务器开启,就会检测RDB文件是否存在,
就会自动载入RDB文件,
注意:若是服务器开启了AOF持久化功能,服务器会优先使用AOF文件来还原数据库状态,
只有在AOF持久化功能关闭的时候,才会使用RDB文件来还原数据库状态。
RDB方式能够自动保存,也能够能够经过手动执行,save命令和bgsave命令
注:利用save命令执行持久化操做时,服务器是被阻塞的,此时redis不能对外提供服务。
bgsave命令执行持久化操做时,服务器是不会被阻塞的,由于是单独启动一个线程来处理
的,建议使用这种方式作数据持久化
Redis.conf配置文件里,有一项配置是和RDB持久相关的参数
save 900 1
save 300 10
save 60 10000
以上表示的意思是,
900秒以内对服务进行了至少一次修改
300秒以内服务器进行了至少10次修改
60秒以内对服务器进行了至少10000次修改。
这些条件知足其中的任意一个bgsave命令就会自动执行。
Redis 数据持久化
2016年1月5日
16:19
分区 新分区 2 的第 18 页
1. Redis默认不是以守护进程的方式运行,能够经过该配置项修改,使用yes启用守护进程
daemonize no
2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,能够经过
pidfile指定
pidfile /var/run/redis.pid
3. 指定Redis监听端口,默认端口为6379,redis做者说由于6379在手机按键上MERZ对应的号
码,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
4. 绑定的主机地址
bind 127.0.0.1
5.当客户端闲置多长时间后关闭链接,若是指定为0,表示关闭该功能
timeout 300
6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为
verbose
loglevel verbose
7. 日志记录方式,默认为标准输出,若是配置Redis为守护进程方式运行,而这里又配置为日
志记录方式为标准输出,则日志将会发送给/dev/null
logfile stdout
8. 设置数据库的数量,默认数据库为0,可使用SELECT <dbid>命令在链接上指定数据库id
databases 16
Redis经常使用参数设置
分区 新分区 2 的第 19 页
databases 16
9. 指定在多长时间内,有多少次更新操做,就将数据同步到数据文件,能够多个条件配合
save <seconds> <changes>
Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个
更改。
10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,若是为了节省
CPU时间,能够关闭该选项,但会致使数据库文件变的巨大
rdbcompression yes
11. 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
12. 指定本地数据库存放目录
dir ./
13. 设置当本机为slave服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从
master进行数据同步
slaveof <masterip> <masterport>
14. 设置同一时间最大客户端链接数,默认无限制,Redis能够同时打开的客户端链接数为Redis
进程能够打开的最大文件描述符数,若是设置maxclients 0,表示不做限制。当客户端链接数
分区 新分区 2 的第 20 页
进程能够打开的最大文件描述符数,若是设置maxclients 0,表示不做限制。当客户端链接数
到达限制时,Redis会关闭新的链接并向客户端返回max number of clients reached错误信息
maxclients 128
15. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis
会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将没法再
进行写入操做,但仍然能够进行读取操做。Redis新的vm机制,会把Key存放内存,Value会存
放在swap区
maxmemory <bytes>
16. 指定是否在每次更新操做后进行日志记录,Redis在默认状况下是异步的把数据写入磁盘,
若是不开启,可能会在断电时致使一段时间内的数据丢失。由于redis自己同步数据文件是按
上面save条件来同步的,因此有的数据会在一段时间内只存在于内存中。默认为no
appendonly no
17. 指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
18. 指定更新日志条件,共有3个可选值:
no:表示等操做系统进行数据缓存同步到磁盘(快)
always:表示每次更新操做后手动调用fsync()将数据写到磁盘(慢,安全)
everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
19. 指定是否启用虚拟内存机制,默认值为no,不开启。
若是开启,则Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出
到内存中
vm-enabled no
分区 新分区 2 的第 21 页
vm-enabled no
20. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
21. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes
22.rdbchecksum no
检查RDB数据的正确性,会牺牲10%的性能,故建议关闭.
=============================================================
redis状态与性能监控
一、redis-benchmark
redis基准信息,redis服务器性能检测
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
100个并发链接,100000个请求,检测host为localhost 端口为6379的redis服务器性能
分区 新分区 2 的第 22 页
Redis 和 Memcache 都是基于内存的数据存储系统,Redis的做者Salvatore Sanfilippo曾经对这两
种基于内存的数据存储系统进行过比较:
Redis支持服务器端的数据操做:Redis相比Memcached来讲,拥有更多的数据结构和并支持更
丰富的数据操做,一般在Memcached里,你须要将数据拿到客户端来进行相似的修改再set回
去。这大大增长了网络IO的次数和数据体积。在Redis中,这些复杂的操做一般和通常的
GET/SET同样高效。因此,若是须要缓存可以支持更复杂的结构和操做,那么Redis会是不错的
选择。
内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而若是
Redis采用hash结构来作key-value存储,因为其组合式的压缩,其内存利用率会高于
Memcached。
性能对比:因为Redis只使用单核,而Memcached可使用多核,因此平均每个核上Redis在
存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于
Redis,虽然Redis最近也在存储大数据的性能上进行优化,可是比起Memcached,仍是稍有逊
色。
一、数据类型支持不一样
与Memcached仅支持简单的key-value结构的数据记录不一样,Redis支持的数据类型要丰富
得多。最为经常使用的数据类型主要由五种:String、Hash、List、Set和Sorted Set
二、内存管理机制不一样
在Redis中,并非全部的数据都一直存储在内存中的。这是和Memcached相比一个最大的
区别。当物理内存用完时,Redis能够将一些好久没用到的value交换到磁盘,可是Redis会缓
存全部的key的信息。
这种特性使得Redis能够保持超过其机器自己内存大小的数据。固然,机器自己的内存必需要
可以保持全部的key,毕竟这些数据是不会进行swap操做的。
对于像Redis和Memcached这种基于内存的数据库系统来讲,内存管理的效率高低是影响系
统性能的关键因素。传统C语言中的malloc/free函数是最经常使用的分配和释放内存的方法,但
是这种方法存在着很大的缺陷:首先,对于开发人员来讲不匹配的malloc和free容易形成内
存泄露;其次频繁调用会形成大量内存碎片没法回收从新利用,下降内存利用率;最后做为系
Redis和Memcached的对比
分区 新分区 2 的第 23 页
存泄露;其次频繁调用会形成大量内存碎片没法回收从新利用,下降内存利用率;最后做为系
统调用,其系统开销远远大于通常函数调用。因此,为了提升内存的管理效率,高效的内存管
理方案都不会直接使用malloc/free调用。Redis和Memcached均使用了自身设计的内存管理
机制,可是实现方法存在很大的差别,下面将会对二者的内存管理机制分别进行介绍。
Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,
将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以彻底解决内存碎
片问题。
当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的
Slab Class,而后经过查询Memcached保存着的该Slab Class内空闲Chunk的列表就能够找
到一个可用于存储数据的Chunk。当一条数据库过时或者丢弃时,该记录所占用的Chunk就
能够回收,从新添加到空闲列表中。
Redis的内存管理主要采用的是包装的mallc/free,相较于Memcached的内存管理方法来
说,要简单不少。
3.数据持久化支持
Redis虽然是基于内存的存储系统,可是它自己是支持内存数据的持久化的,并且提供两种主
要的持久化策略:RDB快照和AOF日志。而memcached是不支持数据持久化操做的。
四、集群管理的不一样
Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,可是全内存毕竟才是
其高性能的本质。做为基于内存的存储系统来讲,机器物理内存的大小就是系统可以容纳的最
大数据量。若是须要处理的数据量超过了单台机器的物理内存大小,就须要构建分布式集群来
扩展存储能力。
Memcached自己并不支持分布式,所以只能在客户端经过像一致性哈希这样的分布式算法来
实现Memcached的分布式存储。当客户端向Memcached集群发送数据以前,首先会经过内
置的分布式算法计算出该条数据的目标节点,而后数据会直接发送到该节点上存储。但客户端
查询数据时,一样要计算出查询数据所在的节点,而后直接向该节点发送查询请求以获取数
据。
分区 新分区 2 的第 24 页
相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式
存储。最新版本的Redis已经支持了分布式存储功能。Redis Cluster是一个实现了分布式且允
许单点故障的Redis高级版本,它没有中心节点,具备线性可伸缩的功能。在数据的放置策略
上,Redis Cluster使用的分布式算法也很简单:crc16( key ) % HASH_SLOTS_NUMBER。
为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。当
Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。
分区 新分区 2 的第 25 页
什么是redis?
Redis 是一个基于内存的高性能key-value数据库
Reids的特色
Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库通通加载在内
存当中进行操做,按期经过异步操做把数据库数据flush到硬盘上进行保存。由于是纯内存操
做,Redis的性能很是出色,每秒能够处理超过10万次读写操做,是已知性能最快的Key-Value
DB。
Redis的出色之处不只仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的
最大限制是1GB,不像memcached只能保存1MB的数据,所以Redis能够用来实现不少有用的功
能,比方说用他的List来作FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set
能够作高性能的tag系统等等。另外Redis也能够对存入的Key-Value设置expire时间,所以也可
以被看成一 个功能增强版的memcached来用。
Redis的主要缺点是数据库容量受到物理内存的限制,不能用做海量数据的高性能读写,所以
Redis适合的场景主要局限在较小数据量的高性能操做和运算上。
Redis支持的数据类型
Redis经过Key-Value的单值不一样类型来区分, 如下是支持的类型:
String
Lists
Set 求交集、并集
Sorted Set
hashes
为何redis须要把全部数据放到内存中?
Redis为了达到最快的读写速度将数据都读到内存中,并经过异步的方式将数据写入磁盘。所
以redis具备快速和数据持久化的特征。若是不将数据放在内存中,磁盘I/O速度为严重影响
redis的性能。在内存愈来愈便宜的今天,redis将会愈来愈受欢迎。
若是设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。
Redis总结
分区 新分区 2 的第 26 页
Redis是单进程单线程的
redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
虚拟内存
当你的key很小而value很大时,使用VM的效果会比较好.由于这样节约的内存比较大.
当你的key不小时,能够考虑使用一些很是方法将很大的key变成很大的value,好比你能够考虑将
key,value组合成一个新的value.
vm-max-threads这个参数,能够设置访问swap文件的线程数,设置最好不要超过机器的核数,若是
设置为0,那么全部对swap文件的操做都是串行的.可能会形成比较长时间的延迟,可是对数据完
整性有很好的保证.
本身测试的时候发现用虚拟内存性能也不错。若是数据量很大,能够考虑分布式或者其余数据

分布式
redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到
master。Slave启动时会链接master来同步数据。
这是一个典型的分布式读写分离模型。咱们能够利用master来插入数据,slave提供检索服务。
这样能够有效减小单个机器的并发访问数量
数据分片模型
为了解决读写分离模型的缺陷,能够将数据分片模型应用进来。
能够将每一个节点当作都是独立的master,而后经过业务实现数据分片。
结合上面两种模型,能够将每一个master设计成由一个master和多个slave组成的模型。
Redis的回收策略
volatile-lru:从已设置过时时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘

分区 新分区 2 的第 27 页
volatile-ttl:从已设置过时时间的数据集(server.db[i].expires)中挑选将要过时的数据淘汰
volatile-random:从已设置过时时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
使用Redis有哪些好处?
(1) 速度快,由于数据存在内存中,相似于HashMap,HashMap的优点就是查找和操做的时间
复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操做都是原子性,所谓的原子性就是对数据的更改要么所有执行,要么所有不
执行
(4) 丰富的特性:可用于缓存,消息,按key设置过时时间,过时后将会自动删除
redis相比memcached有哪些优点?
(1) memcached全部的值均是简单的字符串,redis做为其替代者,支持更为丰富的数据类型
(2) redis的速度比memcached快不少
(3) redis能够持久化其数据
redis常见性能问题和解决方案:
(1) Master最好不要作任何持久化工做,如RDB内存快照和AOF日志文件,可让它的slave来
作持久化工做。
(2) 若是数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
分区 新分区 2 的第 28 页
(3) 为了主从复制的速度和链接的稳定性,Master和Slave最好在同一个局域网内
(4) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <-
Slave3...
这样的结构方便解决单点故障问题,实现Slave对Master的替换。若是Master挂了,能够马上启
用Slave1作Master,其余不变。
MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据
都是热点数据
相关知识:redis 内存数据集大小上升到必定大小的时候,就会施行数据淘汰策略。redis 提供
6种数据淘汰策略
Memcache与Redis的区别都有哪些?
Redis 常见的性能问题都有哪些?如何解决?
1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工做,当快照比较大时对
性能影响是很是大的,会间断性暂停服务,因此Master最好不要写内存快照。
2).Master AOF持久化,若是不重写AOF文件,这个持久化方式对性能的影响是最小的,可是
AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要作任何持
久化工做,包括内存快照和AOF日志文件,特别是不要启用内存快照作持久化,若是数据比较关
键,某个Slave开启AOF备份数据,策略为每秒同步一次。
3).Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导
致服务load太高,出现短暂服务暂停现象。
4). Redis主从复制的性能问题,为了主从复制的速度和链接的稳定性,Slave和Master最好在同
一个局域网内
redis 最适合的场景
分区 新分区 2 的第 29 页
redis 最适合的场景
Redis最适合全部数据in-momory的场景
分区 新分区 2 的第 30 页
 java

相关文章
相关标签/搜索