(一)什么是 Redis?
Redis 是一个 key-value 存储系统. 和 Memcached 类似, 它支持存储的 value 类型相对更多, 包括 string(字符串),list(链表),set(集合),zset(sorted set -- 有序集合)和 hash(哈希类型). 与 Memcached 一样, 为了保证效率, 数据都是缓存在内存中. 区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件, 并且在此基础上实现了 master-slave(主从)同步.
Redis 是一个高性能的 key-value 数据库. Redis 的出现, 很大程度补偿了 Memcached 这类 key/value 存储的不足, 在部分场合可以对关系数据库起到很好的补充作用. 它提供了 Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang 等客户端, 使用很方便.[1]
Redis 支持主从同步. 数据可以从主服务器向任意数量的从服务器上同步, 从服务器可以是关联其他从服务器的主服务器.
(二)Redis 与 Memcached 的区别
u 持久化:
l Redis 可以用来做缓存, 也可以做存储; 支持 ADF 和 RDB 两种持久化方式
l Memcached 只能缓存数据
u 数据结构:
l Redis 有丰富的数据类型: 字符串, 链表, Hash, 集合, 有序集合
l Memcached 一般就是字符串和对象
(三)Redis 的安装与配置
1.解压: tar -zxvf Redis-3.0.5.tar.gz
2.make
3.make PREFIX=/root/training/Redis install
4.cp ~/tools/Redis-3.0.5/Redis.conf /root/training/Redis/etc/
Redis 的核心配置文件: Redis.conf
Redis 的命令脚本:
Redis-benchmark 性能测试工具
Redis-check-aof 检查 AOF 日志
Redis-check-dump 检查 RDB 日志
Redis-cli 启动命令行客户端
Redis-sentinel
Redis-server 启动 Redis 服务
启动 Redis:
- ./Redis-server ../etc/redis6379.conf
- ./Redis-server ../etc/redis6380.conf
这样就在 6379 和 6380 端口上, 各自启动了一个 Redis 实例; 也可以通过 ps 命令查看:
启动 Redis 的客户端: Redis-cli
l 默认连接 6739 端口, 也可以通过 - p 指定连接的端口号:
l ./Redis-cli --help 显式帮助信息
(四)Redis 的操作
http://www.redis.cn/commands.html
key 操作 Redis 的 key 是以 string 储存的, Redis 对于 key 常用的操作指令如下:
1.select db_name 使用指定数据库 select 1 # 使用数据库 1
2.exits key_name 检查指定的 key 是否存在
3.get key_name 获取指定 key 的 value
4.mget key1 [key2 ..] 获取指定多个 key 的 value,
5.randomkey 随机获取一个 key
6.set key_name key_value 设置 key-value
7.getset key_name key_value 设置 key-value, 并返回 key 的旧值
8.setnx key_name value 只有在 key 不存在时, 才设置 key
9.mset key1 val1[ key1 val2...] 同时设置多个 key-value
10.del key_name 删除指定的 key
11.rename key_name new_key_name 重命名指定 key
12.type key_name 返回指定 key 的 value 的类型
13.dump key_name 序列化指定 key, 并返回该 key 序列化后的 value
14.keys pattern 查找所有符合给定 pattern 的 key, 支持使用 * 作为通配符;
15.keys a* # 查找所有以'a' 开头的 key
16.keys * # 查找所有 key
17.move key_name db_name 将指定 key-value 移动到指定数据库
18.expire key_name seconds pexpire key_name milliseconds
给指定 key 设置过期时间, 单位分别为秒, 毫秒
19.expireat key_name timestamp 设置指定的 key 在指定的 UNIX 时间戳过期
20.ttl key_name pttl key_name
返回 key 的 TTL(Time to Live)生存时间, 分别以 秒, 毫秒为单位;
21.persist key_name 移除指定 key 的过期时间, 该 key 将持久保存
22.flushdb 删除当前数据库的所有 key
23.flushall 删除所有数据库的 key
其他操作可进入链接查看
数据类型
1 字符串
2 链表
3 Hash
4 无序集合
5 有序集合
6 Redis 数据类型案例分析: 网站统计用户登录的次数
1 亿个用户, 有经常登录的, 也有不经常登录的
如何来记录用户的登录信息
如何查询活跃用户: 比如: 一周内, 登录 3 次的
解决方案一: 采用关系型数据库
解决方案二: 采用 Redis 存储登录信息
可以使用 Redis 的 setbit, 登录与否: 有 1 和 0 就可以表示
25.Java 客户端
1 基本操作
2 连接池
3 使用 Redis 实现分布式锁
使用 Maven 搭建工程:
- <dependency>
- <groupId>
- Redis.clients
- </groupId>
- <artifactId>
- jedis
- </artifactId>
- <version>
- 2.9.0
- </version>
- </dependency>
(五)Redis 的事务和消息机制
1.Redis 的事务
Redis 对事务的支持目前还比较简单. Redis 只能保证一个 client 发起的事务中的命令可以连续的执行, 而中间不会插入其他 client 的命令. 由于 Redis 是单线程来处理所有 client 的请求的所以做到这点是很容易的. 一般情况下 Redis 在接受到一个 client 发来的命令后会立即处理并 返回处理结果, 但是当一个 client 在一个连接中发出 multi 命令有, 这个连接会进入一个事务上下文, 该连接后续的命令并不是立即执行, 而是先放到一个队列中. 当从此连接受到 exec 命令后, Redis 会顺序的执行队列中的所有命令. 并将所有命令的运行结果打包到一起返回给 client. 然后此连接就 结束事务上下文.
Oracle 数据库中的事务和 Redis 的事务对比
2.Redis 的事务示例: 银行转账
从 Tom 转 100 块钱给 Mike
- set tom 1000
- set mike 1000
- multi
- decrby tom 100
- incrby mike 100
- exec
3.Redis 的锁机制: watch
l 举例: 买票
4.Java 应用程序中的事务和锁
1 事务
2 锁
5.Redis 的消息机制: 消息的发布与订阅, 适合做在线聊天
publish: 发布消息
格式: publish channel 名称 "消息内容"
subscribe: 订阅消息
格式: subscribe channel 名称
psubscribe: 使用通配符定义消息
格式: psubscribe channel * 名称
使用 Java 程序实现消息的发布与订阅, 需要继承 JedisPubSub 类
(六)Redis 的持久化
Redis 提供了多种不同级别的持久化方式:
RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot).
AOF (Append-only file)持久化记录服务器执行的所有写操作命令, 并在服务器启动时, 通过重新执行这些命令来还原数据集. AOF 文件中的命令全部以 Redis 协议的格式来保存, 新命令会被追加到文件的末尾. Redis 还可以在后台对 AOF 文件进行重写(rewrite), 使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小.
Redis 还可以同时使用 AOF 持久化和 RDB 持久化. 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整.
你甚至可以关闭持久化功能, 让数据只在服务器运行时存在.
1,RDB
工作原理: 每隔一定时间给内存照一个快照, 将内存中的数据写入文件 (rdb 文件) 配置参数: Redis.conf 文件(在 conf 文件中找到对应位置)
RDB 示例测试: 可以使用 Redis-benchmark 进行压力测试
./bin/Redis-benchmark -n 100000 表示执行 100000 个操作
RDB 的缺点:
在两次快照之间, 如果发生断电, 数据会丢失
举例: 在生成 rdb 后, 插入新值. 突然断电, 数据可能会丢失
2,AOF: 通过日志的方式
工作原理: 记录操作的命令
配置参数:
什么是 AOF 的重写: rewrite
将内存中的 key 逆向生成命令, 如同一个可以, 反复操作了 100 次, aof 文件会记录 100 次操作, 这样会导致 AOF 文件过大
例如:
- set age 0
- incr age
- incr age
... 100 次
最后 age 的值是 100
经过重写后, 直接执行: set age 100
2. 可以通过观察 aof 日志文件的大小
3,Redis 持久化注意的问题
RDB 恢复的速度快
如果 RDB 和 AOF 都有, 默认使用 AOF 进行恢复
(七)Redis 的集群
1.集群的作用
l 主从备份 防止主机宕机
l 读写分离, 分担 master 的任务
l 任务分离, 如从服分别分担备份工作与计算工作
2.Redis 集群的两种部署方式
3.Redis 主从服务的通信原理
4.配置 Redis 的集群(主从模式)
主节点: 关闭 rdb 和 aof 即可
从节点: slaveof localhost 6379 开启 rdb 和 aof
5.Redis 集群的高可用性
Redis 2.4 + 自带了一个 HA 实现 Sentinel
配置文件: sentinel.conf
Redis-sentinel ../etc/sentinel.conf
查看日志:
6.实现 Redis 的代理分片
Twemproxy 是一种代理分片机制, 由 Twitter 开源.
Twemproxy 作为代理, 可接受来自多个程序的访问, 按照路由规则, 转发给后台的各个 Redis 服务器, 再原路返回. 该方案很好的解决了单个 Redis 实例承载能力的问题.
安装
- ./configure --prefix=/root/training/proxy
- make
- make install
配置文件
检查配置文件是否正确
./nutcracker -t conf/nutcracker.YAML
启动代理服务器
./nutcracker -d -c conf/nutcracker.YAML
(八)****Redis**** Cluster**** 分布式解决方案
1. 什么是 Redis Cluster?
Redis Cluster 是 Redis 的分布式解决方案, 在 Redis 3.0 版本正式推出的, 有效解决了 Redis 分布式方面的需求. 当遇到单机内存, 并发, 流量等瓶颈时, 可以采用 Cluster 架构达到负载均衡的目的.
Redis 使用中遇到的瓶颈
我们日常在对于 Redis 的使用中, 经常会遇到一些问题:
(1) 高可用问题, 如何保证 Redis 的持续高可用性.
(2) 容量问题, 单实例 Redis 内存无法无限扩充, 达到 32G 后就进入了 64 位世界, 性能下降.
(3) 并发性能问题, Redis 号称单实例 10 万并发, 但也是有尽头的.
Redis-cluster 的优势
(1) 官方推荐, 毋庸置疑.
(2) 去中心化, 集群最大可增加 1000 个节点, 性能随节点增加而线性扩展.
(3) 管理方便, 后续可自行增加或摘除节点, 移动分槽等等.
(4) 简单, 易上手.
2. 数据分布理论与 Redis 的数据分区
分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题, 即把数据集划分到多个节点上, 每个节点负责整个数据的一个子集. 常见的分区规则有哈希分区和顺序分区. Redis Cluster 采用哈希分区规则.
虚拟槽分区巧妙地使用了哈希空间, 使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合, 整数定义为槽(slot). 比如 Redis Cluster 槽的范围是 0 ~ 16383. 槽是集群内数据管理和迁移的基本单位.
Redis Cluster 采用虚拟槽分区, 所有的键根据哈希函数映射到 0 ~ 16383, 计算公式: slot = CRC16(key)&16383. 每一个节点负责维护一部分槽以及槽所映射的键值数据.
3.Redis Cluster 的体系架构
我们以 6 个节点为例, 来介绍 Redis Cluster 的体系架构. 其中: 三个为 master 节点, 另外三个为 slave 节点.
4. 安装与部署(方式一: 使用配置文件)
1 Redis 的编译安装
安装 Linux 操作系统和 GCC 编译
编译安装 Redis
解压: tar -zxvf Redis-3.0.5.tar.gz
- make
- make PREFIX=/root/training/Redis install
- cp ~/tools/Redis-3.0.5/Redis.conf /root/training/Redis/etc/
2 安装 Ruby 环境和 Ruby Redis 接口
由于创建和管理需要使用到 Redis-trib 工具, 该工具位于 Redis 源码的 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片 (reshared) 等工作, 所以需要安装 Ruby 环境和相应的 Redis 接口
下面是可以使用 yum 来安装 Ruby:
- [media]
- name=Red Hat Enterprise Linux 7.4
- baseurl=file:///cdroom
- enabled=1
- gpgcheck=1
- gpgkey=file:///cdroom/RPM-GPG-KEY-RedHat-release
3 以 6 个节点为例, 安装和部署 Redis Cluster
主节点: 6379,6380,6381
从节点: 6382,6383,6384
需要修改的参数如下: 其中红色字体部分需要每个实例修改.
- daemonize yes
- port 6379
- cluster-enabled yes
- cluster-config-file nodes/nodes-6379.conf
- cluster-node-timeout 15000
- dbfilename dump6379.rdb
- appendonly yes
- appendfilename "appendonly6379.aof"
配置文件一共六个:
- redis6379.conf
- redis6380.conf
- redis6381.conf
- redis6382.conf
- redis6383.conf
- redis6384.conf
4 启动 Redis 实例
- bin/Redis-server conf/redis6379.conf
- bin/Redis-server conf/redis6380.conf
- bin/Redis-server conf/redis6381.conf
- bin/Redis-server conf/redis6382.conf
- bin/Redis-server conf/redis6383.conf
- bin/Redis-server conf/redis6384.conf
通过 ps 命令查看进程:
5 使用 Redis-trib.rb 自动部署方式
bin/Redis-trib.rb create --replicas 1 192.168.56.72:6379 192.168.56.72:6380 192.168.56.72:6381 192.168.56.72:6382 192.168.56.72:6383 192.168.56.72:6384
注意:****Redis-trib.rb**** 位于 Redis 源码的 src 文件夹 **** 中, 拷贝到 ****bin 目录下.
其中:-replicas 1 表示我们希望为集群中的每个主节点创建一个从节点.
开始配置集群:
6 测试 Redis Cluster
使用客户端登录: bin/Redis-cli -c -p 6379
-c 表示: 登录集群
可以使用: cluster nodes 命令查看集群中的节点
5. 安装与部署(方式二: 使用 create-cluster 命令)
将源码的 utils/create-cluster 目录下, 将 create-cluster 拷贝到安装目录的 bin 目录下
修改 create-cluster 命令的路径
启动和创建 Redis 集群
- bin/create-cluster start
- bin/create-cluster create
使用客户端测试集群
**6. 使用 Java 程序测试 Redis Cluster
jar 包: commons-pool2-2.3.jar jedis-2.7.0.jar**
7. 基本的 Redis Cluster 管理
使用 cluster <command> 命令来管理 Redis Cluster:
命令详解: cluster info
命令详解: cluster nodes(可以使用 Excel 导入命令输出, 方便查看)
几点说明:
ping-sent: 最近一次发送 ping 的时间, 这个时间是一个 unix 毫秒时间戳, 0 代表没有发送过.
pong-recv: 最近一次收到 pong 的时间, 使用 unix 时间戳表示.
config-epoch: 节点的 epoch 值(or of the current master if the node is a slave). 每当节点发生失败切换时, 都会创建一个新的, 独特的, 递增的 epoch. 如果多个节点竞争同一个哈希槽时, epoch 值更高的节点会抢夺到.
命令详解: cluster slots
其他几个命令:
节点的添加与删除
增加节点(每次添加 2 个)
1 增加新的配置文件: redis6385.conf 和 redis6386.conf
2 按照之前的配置修改对应参数
3 启动新的节点
- bin/Redis-server conf/redis6385.conf
- bin/Redis-server conf/redis6386.conf
4 添加主节点
bin/Redis-trib.rb add-node 192.168.56.72:6385 192.168.56.72:6379
其中:
192.168.56.72:6385 是新添加的节点
192.168.56.72:6379 是集群中, 任一个旧节点
5 检查集群的节点信息
bin/Redis-trib.rb check 192.168.56.72:6379
6 添加从节点
bin/Redis-trib.rb add-node --slave --master-id f27013eaebcf998078edf1621e4433534f8d8b11 192.168.56.72:6386 192.168.56.72:6379
其中:
--slave: 表示添加的是一个从节点
--master-id: 表示该从节点的主节点
192.168.56.72:6386: 新添加的从节点
192.168.56.72:6379: 是集群中, 任一个旧节点
7 重新检查集群的状态信息
bin/Redis-trib.rb check 192.168.56.72:6379
8 重新分配 slot
bin/Redis-trib.rb reshard 192.168.56.72:6379
9 重新查看集群的节点槽的信息, 可以看到新添加的节点信息.
cluster slots
或者使用:
bin/Redis-trib.rb check 192.168.56.72:6379
删除节点
1 先删除从节点:
bin/Redis-trib.rb del-node 192.168.56.72:6385 21e3e82610ce206708aa8f4189e2c9b2f3d1c540
2 再删除主节点
bin/Redis-trib.rb del-node 192.168.56.72:6386 f757ce35102b3aaff3621b539e2dc675eafe3c01
3 如果出现以下错误, 需要先清空 (移动) 该节点上的 slot, 再删除
第一步: bin/Redis-trib.rb reshard 192.168.56.72:6386
第二步: bin/Redis-trib.rb del-node 192.168.56.72:6386 f757ce35102b3aaff3621b539e2dc675eafe3c01
4 重新检查集群的信息, 发生节点已经被删除
bin/Redis-trib.rb check 192.168.56.72:6379
8.Redis Cluster 节点的失败迁移
1 首先, 为了看到演示的效果, 清除一下之前的设置, 还是以六个节点为例
2 启动每个节点, 并创建集群
- bin/Redis-server conf/redis6379.conf
- bin/Redis-server conf/redis6380.conf
- bin/Redis-server conf/redis6381.conf
- bin/Redis-server conf/redis6382.conf
- bin/Redis-server conf/redis6383.conf
- bin/Redis-server conf/redis6384.conf
- bin/Redis-trib.rb create --replicas 1 192.168.56.72:6379 192.168.56.72:6380 192.168.56.72:6381 192.168.56.72:6382 192.168.56.72:6383 192.168.56.72:6384
3 检查集群状态
bin/Redis-trib.rb check 192.168.56.72:6379
4 杀掉 6379 上的主节点, 并重新检查集群的状态
5 稍等一段时间, 重新检查集群的状态
6 如果重新启动 6379 上的实例, 它将变成 6382 的从节点
来源: http://www.jianshu.com/p/ac097d341975