redis的详细介绍与测试

redis

  • redis官网:
    https://redis.io/download
  • win版本的redis
    https://github.com/MicrosoftArchive/redis/releases
  • redis安装教程
    http://blog.csdn.net/pf1234321/article/details/78040766

Redis 简介

redis是一种支持Key-Value等多种数据结构的存储系统。可用于缓存,事件发布或订阅,高速队列等场景。提供字符串,哈希,列表,队列,集合结构直接存取,基于内存,可持久化。

  • 菜鸟教程
    http://www.runoob.com/redis/redis-intro.html
  • 引用
    https://blog.csdn.net/middleware2018/article/details/80355418

引入jedis依赖

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.8.0</version>
        </dependency>

redis数据类型

部分函数示例

字符串(String)

set:设值,成功返回1
get:取值
incr:自增1(有自减)
setnx:设值,如果对应的key存在则返回0

        jedis.set("string1","哈喽");
        System.out.println(jedis.get("string1"));
        jedis.set("num","4");
        System.out.println(jedis.incr("num"));// 自增1
        System.out.println(jedis.setnx("string1","aa"));

结果:

服务正在运行:PONG
哈喽
5
0

列表(List)

你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。

lpush:从左边进入
rpush:从右边进入
lpop:移除列表第一个元素并返回该元素
rpop:移除列表最后一个元素并返回该元素

        jedis.lpush("list1","你好");
        jedis.lpush("list1","哈喽");
        List list = jedis.lrange("list1",0,2);
        for (Object l: list){
            System.out.println(l);
        }
        System.out.println(jedis.rpop("list1"));

结果:

哈喽
你好
你好

集合(Set)

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

sadd:向集合添加一个或多个成员
smembers:返回集合中的所有成员

        jedis.sadd("set1","哈哈");
        jedis.sadd("set1","你好");
        System.out.println(jedis.smembers("set1"));
        System.out.println(jedis.sadd("set1","哈哈"));

结果:
添加失败返回0

[哈哈, 你好]
0

有序集合(sorted set)

redis正是通过分数来为有序集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
zadd:向有序集合添加一个或多个成员,或者更新已存在成员的分数

        jedis.zadd("score1",0.2,"php");
        jedis.zadd("score1",0.8,"java");
        jedis.zadd("score1",0.5,"python");
        Set set = jedis.zrange("score",0,2);
        for (Object i:set){
            System.out.println(i);
        }

结果:
按照分数升序排序

php
python
java

哈希(Hash)

是一个string类型的field和value的映射表,hash特别适合用于存储对象
hmset:给指定key赋值(多字段或者map)
hmget:获取所有给定字段的值
hkeys:获取所有哈希表中的字段

        Map map = new HashMap();
        map.put("java","good");
        map.put("python","good too");
        jedis.hmset("hash1", map);
        System.out.println(jedis.hmget("hash1","java"));
        System.out.println(jedis.hkeys("hash1"));

结果:

[good]
[python, java]

redis的应用场景有哪些

  • 会话缓存(最常用)
  • 消息队列(比如支付)
  • 活动排行榜或计数
  • 发布,订阅消息(消息通知)
  • 商品列表,评论列表等

redis的持久化

redis持久有两种方式: 快照(rdb文件),仅附加文件(aof文件)
都在conf配置文件中,默认为快照

快照(RDB)

将存储在内存的数据以快照的方式写入二进制文件中,如默认dump.rdb中

save 900 1
save 300 10
save 60 10000

900秒内如果超过1个Key被修改,则启动快照保存
300秒内如果超过10个Key被修改,则启动快照保存
60秒内如果超过10000个重点被修改,则启动快照保存

# yes启动快照,no关闭
rdbcompression yes

# rdb文件名
dbfilename dump.rdb

仅附加文件(AOF)

使用AOF持久时,服务会将每个收到的写命令通过写函数追加到文件中(appendonly.aof)

#关闭AOF持久化存储方式 
appendonly no

#收到写命令后就立即写入磁盘,效率最差,效果最好
appendfsync always 

#每秒写入磁盘一次,效率与效果居中
appendfsync everysec

#完全依赖操作系统,效率最佳,效果没法保证
appendfsync no   

appendfsync 选项及同步频率

  • always:每个 Redis 命令都要同步写入硬盘。这样会严重降低 Redis 的性能
  • everysec:每秒执行一次同步,显式地将多个写命令同步到硬盘
  • no:让操作系统来决定应该何时进行同步

恢复数据

如果需要恢复数据,只需将备份文件移动到 redis 安装目录并启动服务即可

rdb与aof对比

两种区别就是,一个是持续的用日志记录写操作,crash后利用日志恢复;一个是平时写操作的时候不触发写,只有手动提交save命令,或者是关闭命令时,才触发备份操作。
选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。

redis 分区

分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集

分区的优势

  • 通过利用多台计算机内存的和值,允许我们构造更大的数据库。
  • 通过多核和多台计算机,允许我们扩展计算能力;通过多台计算机和网络适配器,允许我们扩展网络带宽。

分区的不足

  • 当使用分区时,数据处理较为复杂

分区类型

  • 范围分区:
    最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的Redis实例。
    比如,ID从0到10000的用户会保存到实例R0,ID从10001到 20000的用户会保存到R1,以此类推。
  • 哈希分区
    另外一种分区方法是hash分区。用一个hash函数将key转换为一个数字,比如使用crc32 hash函数。

redis集群

redis集群是实现分区的一种方式,Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation)。
这里直接链接:https://www.cnblogs.com/gomysql/p/4395504.html

redis 主从复制

引用: https://www.cnblogs.com/leeSmall/p/8398401.html
主从复制: 主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性

主从复制的相关操作

1.在同目录下复制一份6380.conf配置文件,修改

port 6380
slaveof 127.0.0.1 6379

2.先启动主节点
3.再启动从节点
服务端:redis-server.exe 6380.conf
客户端:redis-cli.exe -p 6380
在这里插入图片描述
4.测试
在从节点先get b没有数据
然后在主节点赋值set b 13
再到从节点get b就有数据了,且为13
在这里插入图片描述
5.断开主从复制:在slave节点,执行6380:>slaveof no one
6.断开后再变成主从复制:6380:> slaveof 127.0.0.1 6379
7.从节点建议用只读模式slave-read-only=yes, 若从节点修改数据,主从数据不一致

传输延迟

主从一般部署在不同机器上,复制时存在网络延时问题,redis提供repl-disable-tcp-nodelay参数决定是否关闭TCP_NODELAY,默认为关闭。
参数关闭时: 无论大小都会及时发布到从节点,占带宽,适用于主从网络好的场景,
参数启用时: 主节点合并所有数据成TCP包节省带宽,默认为40毫秒发一次,取决于内核,主从的同步延迟40毫秒,适用于网络环境复杂或带宽紧张,如跨机房。

数据同步

redis 2.8版本以上使用psync命令完成同步,过程分“全量”与“部分”复制
从服务器可以接受其他从服务器的连接。除了连接多个从服务器到同一个主服务器,从服务器也可以连接到其他的从服务器,形成图状结构。
全量复制: 一般用于初次复制场景(第一次建立SLAVE后全量)
部分复制: 网络出现问题,从节点再次连接主节点时,主节点补发缺少的数据,每次数据增量同步
心跳: 主从有长连接心跳,主节点默认每10S向从节点发ping命令,repl-ping-slave-period控制发送频率

Redis哨兵机制(Sentinel)

主从的缺点

主从复制,若主节点出现问题,则不能提供服务,需要人工修改配置将从变主,无法实现高可用。

原理

当主节点出现故障时,由Redis Sentinel自动完成故障发现和转移,并通知应用方,实现高可用性。

  • 哨兵的定时监控任务
  • 领导者哨兵选举流程
  • 故障转移机制
    过滤掉不健康的(下线或断线),没有回复过哨兵ping响应的从节点
    选择salve-priority从节点优先级最高(redis.conf)的
    选择复制偏移量最大,指复制最完整的从节点

如何安装和部署哨兵

  1. 先搭好一主两从redis的主从复制,和之前的主从复制搭建一样
    从节点:6380.conf
    从节点:6381.conf
  2. 新增sentinel.conf 文件,默认是没有的
    sentinel-26379.conf
    sentinel-26380.conf
    sentinel-26381.conf
#sentinel端口,默认23679
port 26379
#工作路径,注意路径不要和主重复
dir "redis-6379"
# 守护进程模式
daemonize yes
#关闭保护模式
#protected-mode no
# 指明日志文件名
#logfile "sentinel.log"
#哨兵监控的master,主从配置一样,这里只用输入redis主节点的ip/port和法定人数。
sentinel monitor mymaster 127.0.0.1 6379 2
# master或slave多长时间(默认30秒)不能使用后标记为s_down状态。
sentinel down-after-milliseconds mymaster 5000
#若sentinel在该配置值内未能完成failover操作(即故障时master/slave自动切换),则认为本次failover失败。
sentinel failover-timeout mymaster 18000
#设置master和slaves验证密码
#sentinel auth-pass mymaster 123456 

# 指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步
sentinel parallel-syncs mymaster 1

启动测试

  1. 启动主节点
  2. 启动哨兵:
    redis-server.exe sentinel-26379.conf --sentinel
    redis-server.exe sentinel-26380.conf --sentinel
    redis-server.exe sentinel-26381.conf --sentinel
    在这里插入图片描述
  3. 启动从节点:
    redis-server.exe 6380.confredis-server.exe 6380.conf
    redis-server.exe 6380.confredis-server.exe 6381.conf
  4. 哨兵监测
    监控节点启动、关闭
    在这里插入图片描述

选举测试

杀掉端口6379进程
netstat -ano找到6379端口的PID为10496
在这里插入图片描述
taskkill /pid 16496 -f
在这里插入图片描述
观察哨兵,发现6379端口主节点挂掉了,选举了从节点端口6380为新主节点
在这里插入图片描述
在6380客户端查看信息info replication,已成为主节点且从节点为6381端口
在这里插入图片描述

部署建议

  1. sentinel节点应部署在多台物理机(线上环境)
  2. 至少三个且奇数个sentinel节点2.,至少三个且奇数个sentinel节点
  3. 通过以上我们知道,3个sentinel可同时监控一个主节点或多个主节点
    监听N个主节点较多时,如果sentinel出现异常,会对多个主节点有影响,同时还会造成sentinel节点产生过多的网络连接,一般线上建议还是, 3个sentinel监听一个主节点

缓存雪崩和缓存穿透

转自:Hollis公众号

缓存雪崩是什么?

假设有如下一个系统,高峰期请求为5000次/秒,4000次走了缓存,只有1000次落到了数据库上,数据库每秒1000的并发是一个正常的指标,完全可以正常工作,但如果缓存宕机了,每秒5000次的请求会全部落到数据库上,数据库立马就死掉了,因为数据库一秒最多抗2000个请求,如果DBA重启数据库,立马又会被新的请求打死了,这就是缓存雪崩。
在这里插入图片描述

如何解决缓存雪崩

事前:redis高可用,主从+哨兵,redis cluster,避免全盘崩溃
事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL被打死
事后:redis持久化,快速恢复缓存数据

缓存穿透是什么?

假如客户端每秒发送5000个请求,其中4000个为黑客的恶意攻击,即在数据库中也查不到。举个例子,用户id为正数,黑客构造的用户id为负数,
如果黑客每秒一直发送这4000个请求,缓存就不起作用,数据库也很快被打死。
在这里插入图片描述

如何解决缓存穿透

查询不到的数据也放到缓存,value为空,如set -999 “”
总而言之,缓存雪崩就是缓存失效,请求全部全部打到数据库,数据库瞬间被打死。缓存穿透就是查询了一个一定不存在的数据,并且从存储层查不到的数据没有写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值