点击上方“芋道源码”,选择“置顶公众号”
技术文章第一时间送达!
源码精品专栏
精尽 Dubbo 原理与源码 69 篇
精尽 Netty 原理与源码 61 篇
来源:http://t.cn/EwMvakT
5. keys 命令
5.1 常用命令
keys 返回满足给定pattern 的所有key redis 127.0.0.1:6379> keys mylist*
"mylist"
"mylist5"
"mylist6"
"mylist7"
"mylist8"
exists 确认一个key 是否存在 示例:从结果来看,数据库中不存在HongWan 这个key,但是age 这个key 是存在的 redis 127.0.0.1:6379> exists HongWan (integer) 0 redis 127.0.0.1:6379> exists age (integer) 1 redis 127.0.0.1:6379>
del 删除一个key redis 127.0.0.1:6379> del age (integer) 1 redis 127.0.0.1:6379> exists age (integer) 0
rename 重命名key 示例:age 成功的被我们改名为age_new 了 redis 127.0.0.1:6379[1]> keys *
"age" redis 127.0.0.1:6379[1]> rename age age_new OK redis 127.0.0.1:6379[1]> keys *
"age_new" redis 127.0.0.1:6379[1]>
type 返回值的类型 示例:这个方法可以非常简单的判断出值的类型 redis 127.0.0.1:6379> type addr string redis 127.0.0.1:6379> type myzset2 zset redis 127.0.0.1:6379> type mylist list redis 127.0.0.1:6379>
5.2 设置 key 的生存时间
Redis在实际使用过程中更多的用作缓存,然而缓存的数据一般都是需要设置生存时间的,即:到期后数据销毁。
| EXPIRE key seconds | 设置key的生存时间(单位:秒)key在多少秒后会自动删除 |
| TTL key | 查看key剩余的生存时间 |
| PERSIST key | 清除生存时间 |
| PEXPIRE key milliseconds | 生存时间设置单位为:毫秒 |
例子:
192.168.101.3:7002> set test 1 设置test的值为1
OK
192.168.101.3:7002> get test 获取test的值
"1"
192.168.101.3:7002> EXPIRE test 5 设置test的生存时间为5秒
(integer) 1
192.168.101.3:7002> TTL test 查看test的生于生成时间还有1秒删除
(integer) 1
192.168.101.3:7002> TTL test
(integer) -2
192.168.101.3:7002> get test 获取test的值,已经删除
(nil)
6. Redis 持久化方案
6.1 Rdb 方式
Redis 默认的方式,redis 通过快照方式将数据持久化到磁盘中。
6.1.1 设置持久化快照的条件
在 redis.conf 中修改持久化快照的条件:
6.1.2 持久化文件的存储目录
在 redis.conf 中可以指定持久化文件的存储目录
6.1.3 Rdb 的问题
一旦redis非法关闭,那么会丢失最后一次持久化之后的数据。
如果数据不重要,则不必要关心。 如果数据不能允许丢失,那么要使用 aof 方式。
6.2 Aof 方式
Redis 默认是不使用该方式持久化的。Aof 方式的持久化,是操作一次 redis 数据库,则将操作的记录存储到 aof 持久化文件中。
第一步:开启 aof 方式持久化方案。 将redis.conf中的appendonly改为yes,即开启aof方式的持久化方案。
img Aof文件存储的目录和rdb方式的一样。 Aof文件存储的名称
img
在使用aof和rdb方式时,如果redis重启,则数据从aof文件加载。
7. Redis 的主从复制
7.1 什么是主从复制
持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制就可以避免这种单点故障,如下图:
说明:
主redis中的数据有两个副本(replication)即从redis1和从redis2,即使一台redis服务器宕机其它两台redis服务也可以继续提供服务。
主redis中的数据和从redis上的数据保持实时同步,当主redis写入数据时通过主从复制机制会复制到两个从redis服务上。
只有一个主redis,可以有多个从redis。
主从复制不会阻塞master,在同步数据时,master 可以继续处理client 请求
一个redis可以即是主又是从,如下图:
img
7.2 主从复制设置
7.2.1 主机配置
无需配置
7.2.2 从机配置
第一步:复制出一个从机
cp bin/ bin2 -r第二步:修改从机的 redis.conf 语法:slaveof masterip masterport slaveof 192.168.242.137 6379
img 第三步:修改从机的 port 地址为 6380
img 第四步:清除从机的持久化文件
rm -rf appendonly.aof dump.rdb第五步:启动从机
./redis-server redis.conf第六步:启动6380的客户端
./redis-cli -p 6380
注意: 主机一旦发生增删改操作,那么从机会将数据同步到从机中 从机不能执行写操作
8. Redis 集群
8.1 redis-cluster 架构图
架构细节: (1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽. (2)节点的fail是通过集群中超过半数的节点检测失效时才生效. (3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可 (4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点.
8.2 redis-cluster 投票 容错
(1)集群中所有master参与投票,如果半数以上master节点与其中一个master节点通信超过(cluster-node-timeout),认为该master节点挂掉. (2):什么时候整个集群不可用(cluster_state:fail)?
如果集群任意master挂掉,且当前master没有slave,则集群进入fail状态。也可以理解成集群的[0-16383]slot映射不完全时进入fail状态。
如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态。
8.3 安装 Ruby
集群管理工具(redis-trib.rb)是使用 ruby 脚本语言编写的。
安装 ruby
sudo apt-get install ruby
上传 redis-3.0.0.gem 到 linux
安装 ruby 和 redis 接口
gem install redis-3.0.0.gem将 redis-3.0.0 包下 src 目录中的以下文件拷贝到 redis/redis-cluster/
cd /usr/local/redis/
mkdir redis-cluster
cd /root/redis-3.0.0/src/
cp redis-trib.rb /usr/local/redis/redis-cluster
8.4 搭建集群
搭建集群最少需要 3 台主机,如果每台主机再配置一台从机的话,则最少需要6台机器。 端口设计:7001-7006
复制出一个7001机器
cp bin ./redis-cluster/7001 -r如果存在持久化文件,则删除
rm -rf appendonly.aof dump.rdb设置集群参数,修改redis.conf
img 修改端口
img 复制出7002-7006机器
cp 7001/ 7002-r
cp 7001/ 7003-r
cp 7001/ 7004-r
cp 7001/ 7005-r
cp 7001/ 7006-r
修改7002-7006机器端口
创建文件 start-all.sh
cd 7001
./redis-server redis.conf
cd ..
cd 7002
./redis-server redis.conf
cd ..
cd 7003
./redis-server redis.conf
cd ..
cd 7004
./redis-server redis.conf
cd ..
cd 7005
./redis-server redis.conf
cd ..
cd 7006
./redis-server redis.conf
cd ..
修改文件权限
chmod u+x start-all.sh
执行文件,启动六台机器
./start-all.sh
创建集群
./redis-trib.rb create --replicas 1 192.168.126.128:7001 192.168.126.128:7002 192.168.126.128:7003 192.168.126.128:7004 192.168.126.128:7005 192.168.126.128:7006
8.5 连接集群
root@ubuntu:/usr/local/redis/redis-cluster/7001# ./redis-cli -p 7001 -c
-c 指定集群连接
8.6 查看集群信息
查看集群信息
192.168.126.128:7002> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_sent:260
cluster_stats_messages_received:260查看集群节点
192.168.126.128:7002> cluster nodes
3a15e73dacb512745156535ae7f959acf65ae12e 192.168.126.128:7005 slave 23e173cdc0b7673dc28cae70efaabbc41308bfdc 0 1531452321139 5 connected
2a58a53a5b10f7bd91af04128a6ed439d534c0ee 192.168.126.128:7001 master - 0 1531452322145 1 connected 0-5460
d0808388485dd08f1a2ecdfe3d2b213742d0050d 192.168.126.128:7004 slave 2a58a53a5b10f7bd91af04128a6ed439d534c0ee 0 1531452318117 4 connected
23e173cdc0b7673dc28cae70efaabbc41308bfdc 192.168.126.128:7002 myself,master - 0 0 2 connected 5461-10922
2af2312acc56552f9f73470f90d9a51973fc74d3 192.168.126.128:7006 slave 78faf92cfdbd12e1b27b270fb0798e67017f4d0b 0 1531452320132 6 connected
78faf92cfdbd12e1b27b270fb0798e67017f4d0b 192.168.126.128:7007 master - 0 1531452319123 3 connected 10923-16383
8.7 jedis连接集群
@Test
public void jedisCluster() {
// 创建jedisCluster
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.242.137", 7001));
nodes.add(new HostAndPort("192.168.242.137", 7002));
nodes.add(new HostAndPort("192.168.242.137", 7003));
nodes.add(new HostAndPort("192.168.242.137", 7004));
nodes.add(new HostAndPort("192.168.242.137", 7005));
nodes.add(new HostAndPort("192.168.242.137", 7006));
nodes.add(new HostAndPort("192.168.242.137", 7007));
JedisCluster cluster = new JedisCluster(nodes);
cluster.set("s4", "444");
String result = cluster.get("s4");
System.out.println(result);
cluster.close();
}
8.8 使用 spring
配置 applicationContext.xml
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="30" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="10" />
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="true" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<!-- redis集群 -->
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg index="0">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.101.3"></constructor-arg>
<constructor-arg index="1" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.101.3"></constructor-arg>
<constructor-arg index="1" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.101.3"></constructor-arg>
<constructor-arg index="1" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.101.3"></constructor-arg>
<constructor-arg index="1" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.101.3"></constructor-arg>
<constructor-arg index="1" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg index="0" value="192.168.101.3"></constructor-arg>
<constructor-arg index="1" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
<constructor-arg index="1" ref="jedisPoolConfig"></constructor-arg>
</bean>
测试代码
private ApplicationContext applicationContext;
@Before
public void init() {
applicationContext = new ClassPathXmlApplicationContext(
"classpath:applicationContext.xml");
}
// redis集群
@Test
public void testJedisCluster() {
JedisCluster jedisCluster = (JedisCluster) applicationContext
.getBean("jedisCluster");
jedisCluster.set("name", "zhangsan");
String value = jedisCluster.get("name");
System.out.println(value);
}
如果你对 Dubbo / Netty 等等源码与原理感兴趣,欢迎加入我的知识星球一起交流。长按下方二维码噢:

目前在知识星球更新了《Dubbo 源码解析》目录如下:
01. 调试环境搭建
02. 项目结构一览
03. 配置 Configuration
04. 核心流程一览
05. 拓展机制 SPI
06. 线程池
07. 服务暴露 Export
08. 服务引用 Refer
09. 注册中心 Registry
10. 动态编译 Compile
11. 动态代理 Proxy
12. 服务调用 Invoke
13. 调用特性
14. 过滤器 Filter
15. NIO 服务器
16. P2P 服务器
17. HTTP 服务器
18. 序列化 Serialization
19. 集群容错 Cluster
20. 优雅停机
21. 日志适配
22. 状态检查
23. 监控中心 Monitor
24. 管理中心 Admin
25. 运维命令 QOS
26. 链路追踪 Tracing
... 一共 69+ 篇
目前在知识星球更新了《Netty 源码解析》目录如下:
01. 调试环境搭建
02. NIO 基础
03. Netty 简介
04. 启动 Bootstrap
05. 事件轮询 EventLoop
06. 通道管道 ChannelPipeline
07. 通道 Channel
08. 字节缓冲区 ByteBuf
09. 通道处理器 ChannelHandler
10. 编解码 Codec
11. 工具类 Util
... 一共 61+ 篇
目前在知识星球更新了《数据库实体设计》目录如下:
01. 商品模块
02. 交易模块
03. 营销模块
04. 公用模块
... 一共 17+ 篇
目前在知识星球更新了《Spring 源码解析》目录如下:
01. 调试环境搭建
02. IoC Resource 定位
03. IoC BeanDefinition 载入
04. IoC BeanDefinition 注册
05. IoC Bean 获取
06. IoC Bean 生命周期
... 一共 35+ 篇
源码不易↓↓↓↓↓
点赞支持老艿艿↓↓
全面解析Redis关键技术,涵盖数据操作、持久化、主从复制及集群搭建,深入探讨Redis在缓存、高可用及分布式场景下的应用。
3420

被折叠的 条评论
为什么被折叠?



