企业缓存产品介绍
Memcached:
优点:高性能读写、单一数据类型、支持客户端式分布式集群、一致性hash。多核结构、多线程读写性能高。
缺点:无持久化、节点故障可能出现缓存穿透、分布式需要客户端实现、跨机房数据同步困难、架构扩容复杂度高
Redis:
优点:高性能读写、多数据类型支持、数据持久化、高可用架构、支持自定义虚拟内存、支持分布式分片集群、单线程读写性能极高。
缺点:多线程读写较Memcached慢。
Tair:
优点:高性能读写、支持三种存储引擎(ddb、rdb、ldb)、支持高可用、支持分布式分片集群、支撑了几乎所有淘宝业务的缓存。
缺点:单机情况下,读写性能较其他两种产品较慢。
使用场景介绍:
- Memcached:多核的缓存服务,更加适合于多用户并发访问次数较少的应用场景
- Redis:单核的缓存服务,单节点情况下,更加适合于少量用户,多次访问的应用场景。
Redis 功能介绍
- 数据类型丰富
- 支持持久化
- 多种内存分配及回收策略
- 支持弱事务
- 消息队列、消息订阅
- 支持高可用
- *支持分布式分片集群
- 缓存穿透雪崩
- Redis API
Redis 单机安装(3.2.12 版本)
软件下载
# 下载软件包
wget http://download.redis.io/releases/redis-3.2.12.tar.gz
# 解压
tar xzf redis-3.2.12.tar.gz -C /application
# 设置软连接
ln -s /application/redis-3.2.12/ /application/redis
安装
# 安装依赖
yum -y install gcc automake autoconf libtool make
# 编译
cd /application/redis
make
环境变量
# 添加环境变量
echo 'export PATH=/application/redis/src:$PATH' >>/etc/profile
# 生效环境变量
source /etc/profile
启动Redis
redis-server &
连接测试
# 进入redis交互
redis-cli
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> get num
"10"
Redis 基本管理
基础配置文件介绍
# 创建目录
mkdir -p /data/redis/6379
# 创建redis配置文件
[root@redis ~]# vim /data/redis/6379/redis.conf
#是否后台运行
daemonize yes
#端口号
port 6379
#redis 日志文件
logfile /data/redis/6379/redis.log
#持久化文件存储位置
dir /data/redis/6379
#RDB持久化数据文件
dbfilename dump.rdb
重启/检查
# 关闭
redis-cli shutdown
# 启动,指定redis.conf
redis-server /data/6379/redis.conf
# 查看端口是否启动
netstat -lntup|grep 6379
Redis 安全配置
Redis默认开启了保护模式,只允许本地回环地址登录并访问数据库。
解决方法
- Bind :指定IP进行监听
- 增加requirepass {password}
配置方法
[root@db01 redis]# vim /data/redis/6379/redis.conf
# 监听地址(允许连接Redis的地址)
bind 127.0.0.1 10.4.7.51
# 连接Redis的密码
requirepass 123456
验证
# 方法一: 命令行指定密码( -a )
[root@db01 redis]# redis-cli -a 123456 -h 10.4.7.51
10.4.7.51:6379> set name Zoro
OK
10.4.7.51:6379> get name
"Zoro"
# 方法二: 内部验证( AUTH )
[root@db01 redis]# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> get name
"Zoro"
# 指定端口
[root@db01 redis]# redis-cli -a 123456 -h 10.4.7.51 -p 6379
Redis 持久化配置
内存数据保存到磁盘。可以有效防止,在redis 宕机后,缓存失效的问题。
持久化分类
-
RDB 持久化
特点:可以在指定的时间间隔内生成数据集的时间点快照。
优点:速度快,适合于用作备份,主从复制也是基于RDB持久化功能实现的。
缺点:可能会有数据丢失。
-
AOF 持久化
特点:记录服务器执行的所有变更操作,并在服务器启动时,通过重新执行这些命令来还原数据集。
AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。优点:可以最大程度保证数据不丢。
缺点:日志记录量级比较大。
RDB 持久化配置
[root@db01 ~]# vim /data/redis/6379/redis.conf
#RBD持久化文件目录
dir /data/redis/6379
#RBD持久化文件
dbfilename dump.rdb
#RBD自动持久化功能配置
save 900 1
save 300 10
save 60 10000
#################
配置分别表示:
900秒 内有1个更改,执行save
300秒 内有10个更改,执行save
60秒 内有10000个更改,执行save
AOF 持久化配置
[root@db01 ~]# vim /data/redis/6379/redis.conf
#是否打开aof日志功能
appendonly yes
#刷写策略
appendfsync everysec
## 刷写策略:
appendfsync always -- 每一个命令,都立即同步到aof
appendfsync everysec -- 每秒写1次
appendfsync no -- 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof
Redis 持久化方式与区别
- RDB:基于快照的持久化,速度更快,一般用作备份,主从复制也是依赖于rdb持久化功能
- AOF:以追加的方式记录redis操作日志的文件。可以最大程度的保证redis数据安全,类似于mysql的binlog
Redis 数据类型
String 字符串类型
string 是 redis 最基本的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。
String 应用场景:session 共享,常规计数(微博数,粉丝数,订阅、礼物等)
Hash 哈希类型
Redis中的散列可以看成具有String key和String value的map容器,可以将多个key-value存储到一个key中。每一个Hash可以存储4294967295个键值对。
Hash 应用场景:存储一些结构化的数据,比如用户的昵称、年龄、性别、积分等,存储一个用户信息对象数据。
List 列表类型
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或者尾部.
List中可以包含的最大元素数量是4294967295。
List应用场景:经常会被用于消息队列的服务,以完成多程序之间的消息交换。
Set 集合类型(join union)
edis的Set是string类型的无序集合。和列表一样,在执行插入和删除和判断是否存在某元素时,效率是很高的。集合最大的优势在于可以进行交集并集差集操作。Set可包含的最大元素数量是4294967295。
应用场景:1.利用交集求共同好友。2.利用唯一性,可以统计访问网站的所有独立IP。3.好友推荐等
SortedSet(有序集合)
和set很像,都是字符串的集合,都不允许重复的成员出现在一个set中。他们之间差别在于有序集合中每一个成员都会有一个分数(score)与之关联,Redis正是通过分数来为集合中的成员进行自动排序。尽管有序集合中的成员必须是唯一的,但是分数(score)却可以重复。
应用场景:排行榜应用,取TOP N操作等
Redis 发布订阅
PUBLISH channel msg
将信息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel ...]
订阅频道,可以同时订阅多个频道
UNSUBSCRIBE [channel ...]
取消订阅指定的频道, 如果不指定频道,则会取消订阅所有频道
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所 有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类
PUNSUBSCRIBE [pattern [pattern ...]]
退订指定的规则, 如果没有参数则会退订所有规则
PUBSUB subcommand [argument [argument ...]]
查看订阅与发布系统状态
注意:使用发布订阅模式实现的消息队列,当有客户端订阅channel后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须Provider和Consumer同时在线。
举例说明
-- 发布订阅例子
# 窗口1:订阅频道 zzgw
127.0.0.1:6379> SUBSCRIBE zzgw
#窗口2: 在zzgw频道发布消息
127.0.0.1:6379> PUBLISH zzgw 'www.onelpc.com'
#窗口1: 订阅者的客户端输出
1) "message"
2) "zzgw"
3) "www.onelpc.com"
-- 订阅多频道:
# 窗口1:订阅频道:aa zz*(zz开头的)
127.0.0.1:6379> PSUBSCRIBE aa zz*
#窗口2:发表消息
127.0.0.1:6379> PUBLISH aa 'this is aaa'
127.0.0.1:6379> PUBLISH zz 'this is zzz'
127.0.0.1:6379> PUBLISH zz1 'this is zzz1'
#订阅者的客户端输出
1) "pmessage"
2) "aa"
3) "aa"
1) "pmessage"
2) "zz*"
3) "zz"
4) "this is zzz"
1) "pmessage"
2) "zz*"
3) "zz1"
4) "this is zzz1"
Redis 弱事务
Redis的事务是基于队列实现的。redis 是乐观锁机制
MULTI -- 用于标记事务块的开始。
EXEC -- 在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。
DISCARD -- 清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。
WATCH -- 当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的。
UNWATCH -- 清除所有先前为一个事务监控的键。
举个栗子
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> DISCARD #DISCARD,事务被清除
OK
127.0.0.1:6379> get a
(nil)
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a 1
QUEUED
127.0.0.1:6379> EXEC #EXEC,事务被执行
1) OK
127.0.0.1:6379> get a
"1"
Redis 服务器管理命令
info # 工作情况(内存使用状态)
-- info memory #内存情况(used_memory_rss_human)
-- INFO Replication #主从状态
config get * # 查看Redis状态
config set * # 修改redis信息
Dbsize # key的个数
FLUSHALL # 清空所有数据(生产禁用)
Client list # 连接列表
Client kill ip:port # 杀死连接
CONFIG RESETSTAT # 重置统计
CONFIG GET/SET # 动态修改
select # 切换库,redis支持16个库(0-16),默认是0
FLUSHDB # 清空当前库
MONITOR # 监控实时指令(redis-cli -a 123456 monitor >/tmp/redis.txt)
SHUTDOWN # 关闭Redis服务器
Redis 主从(Master-Replicaset)
Master-Replicaset 架构
Master-Replicaset 原理
1)副本库通过 slaveof 命令,连接主库,在发送SYNC给主库
2)主库收到SYNC,会立即触发BGSAVE,后台保存RDB,发送给副本库
3)副本库接收后会应用RDB快照
4)主库会陆续将中间产生的行的操作,保存并发送给副本库
5)到此,主复制集就正常工作了
6)再次之后,主库只要发生新的操作,都会以命令传播的形式自动发送给副本库
7)所有复制相关信息,从info信息中都可以查到,即使重启任何节点,他的主从关系依然存在
8)如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
9)主库只会将从库确实部分的数据同步给从库应用,达到快速恢复主从的目的
主从数据一致性保证
min-slaves-to-write 1 ## 最小从服务器数
min-slaves-max-lag 3 ## 指定网络延迟的最大值
##如果条件不满足,主服务器会拒绝写操作并返回一个错误。
Master-Replicaset 实现
环境准备
mkdir -p /data/638{0..2}
配置文件示例
# 6380实例
cat >/data/6380/redis.conf <<EOF
port 6380
daemonize yes
pidfile /data/6380/redis.pid
loglevel notice
logfile /data/6380/redis.log
dbfilename dump.rdb
dir /data/6380
requirepass 123
masterauth 123
EOF
# 6381实例
cat >/data/6381/redis.conf<<EOF
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile /data/6381/redis.log
dbfilename dump.rdb
dir /data/6381
requirepass 123
masterauth 123
EOF
# 6382实例
cat >/data/6382/redis.conf<<EOF
port 6382
daemonize yes
pidfile /data/6382/redis.pid
loglevel notice
logfile /data/6382/redis.log
dbfilename dump.rdb
dir /data/6382
requirepass 123
masterauth 123
EOF
启动集群
redis-server /data/6380/redis.conf
redis-server /data/6381/redis.conf
redis-server /data/6382/redis.conf
开启主从复制
# 从库操作(6381,6382)
redis-cli -p 6381 -a 123 SLAVEOF 127.0.0.1 6380
redis-cli -p 6382 -a 123 SLAVEOF 127.0.0.1 6380
查询主从状态
redis-cli -p 6381 -a 123 info replication #从库
redis-cli -p 6382 -a 123 info replication #从库
# 主库查看
redis-cli -p 6380 -a 123 info replication #主库
---------------------------------------------------------
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=127,lag=0
slave1:ip=127.0.0.1,port=6382,state=online,offset=127,lag=0
master_repl_offset:127
Master-Replicaset 问题
一旦主节点宕机,从节点上位,需要人为修改所有应用方的主节点地址(改为新的master地址),还需要命令所有从节点复制新的主节点。
Redis-sentinel(哨兵)
Redis-Sentinel是Redis官方推荐的高可用性解决方案,当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能。
而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群,自动发现master宕机,进行自动切换slave > master。
Redis-Sentinel 主要功能
- 监控:定期检测Redis 数据节点、其他 Sentinel 节点是否可达。
- 通知:将故障转移的结果通知给应用方。
- 故障转移:实现从节点晋升为主节点,并维护后续正确的主从关系
- 配置提供:客户端在初始化的时候连接 Sentinel 节点集合,从中获取主节点信息。
多个 Sentinel 节点来共同判断故障,可以有效防止误判,同时如果个别 Sentinel 节点不可用,整个 Sentinel 节点集合依然是高可用的。
Redis-Sentinel 架构
Redis-Sentinel 配置
配置文件准备
# 创建目录
mkdir /data/2638{0..2}
# 26380节点
cat >/data/26380/sentinel.conf<<EOF
port 26380
dir "/data/26380"
logfile 'sentinel.log'
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel auth-pass mymaster 123
EOF
# 26381节点
cat >/data/26381/sentinel.conf<<EOF
port 26381
dir "/data/26381"
logfile 'sentinel.log'
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel auth-pass mymaster 123
EOF
# 26382节点
cat >/data/26382/sentinel.conf<<EOF
port 26382
dir "/data/26382"
logfile 'sentinel.log'
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel auth-pass mymaster 123
EOF
启动 redis-sentinel
redis-sentinel /data/26380/sentinel.conf &
redis-sentinel /data/26381/sentinel.conf &
redis-sentinel /data/26382/sentinel.conf &
检查
redis-cli -p 26380 -a 123 info sentinel
---------------------------------------
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=3
# sentinels=3 说明三个sentinels启动成功
Redis-Sentinel 测试
模拟6380(master)节点故障
redis-cli -p 6380 shutdown
# 查看6381节点,被去哪
role:master
connected_slaves:1
查看6381节点(被选为新master节点)
[root@db01 ~]# redis-cli -a 123 -p 6381 info replication
role:master
connected_slaves:1
查看6382节点(slave节点,指向了新master节点6381)
[root@db01 ~]# redis-cli -a 123 -p 6382 info replication
role:slave
master_host:127.0.0.1
master_port:6381
模拟6380节点恢复(作为slave节点自动恢复主从关系)
[root@db01 ~]# redis-cli -a 123 -p 6380 info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381