Redis客户端的使用&Redis其他功能&持久化的取舍和选择
3. Redis客户端的使用
3-1 课程目录
3-2 Java客户端:Jedis
Jedis是什么
获取Jedis
Maven依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
#1.生成一个Jedis对象,这个对象负责和指定Redis节点进行通信Jedis jedis=new Jedis("127.0.0.1",6379);
#2.jedis执行set操作
jedis.set("hello","world");
#3.jedis执行get操作,value="world"
String value=jedis.get("hello");
构造函数常用参数
Jedis(String host,int port,int connectionTimeout,int soTimeout)
·host:Redis节点的所在机器的IP
·port:Redis节点的端口
·connectionTimeout:客户端连接超时
·soTimeout:客户端读写超时
//1.生成一个Jedis对象,这个对象负责和指定Redis节点进行通信
Jedis jedis = new Jedis("127.0.0.1", 6379);
//1.string
jedis.set("hello","world");
//输出结果:world jedis.get("hello");
// 输出结果:1
jedis.incr("counter");
//2.hash
jedis.hset("myhash","f1","v1");
jedis.hset("myhash","f2","v2");
//输出结果:{f1=v1,f2=v2}
jedis.hgetAll("myhash");
//3.list
jedis.rpush("mylist","1");
jedis.rpush("mylist","2");
jedis.rpush("mylist","3");
///输出结果:[1,2,3]
jedis.lrange("mylist",0,-1);
//4.set
jedis.sadd("myset","a");
jedis.sadd("myset","b");
jedis.sadd("myset","a");
//输出结果:[b,a]
jedis.smembers("myset");
//5.zset
jedis.zadd("myzset",99,"tom");
jedis.zadd("myzset",66,"peter");
jedis.zadd("myzset",33,"james");
//输出结果:[["james"],33.0],[["peter"],66.0],["tom"],99.0]]
jedis.zrangeWithScores("myzset",0,-1);
Jedis连接池使用
◆Jedis直连
◆Jedis连接池
◆方案对比
◆JedisPool使用
public void useJedisPool(){
//初始化Jedis连接池,通常来讲JedisPool是单例的。
GenericObjectPoolConfig poolConfig=new GenericObjectPoolConfig();
JedisPool jedisPool =new JedisPool(poolConfig,"127.0.0.1",6379);
Jedis jedis = null;
try {
//1.从连接池获取jedis对象
jedis = jedisPool.getResource());
//2.执行操作
jedis.set("hello","world");
} catch(Exception e){
e.printStackTrace();
}finally{
if(jedis!=null);
//如果使用JedisPool,close操作不是关闭连接,代表归还连接池jedis.close0;
}
}
4.瑞士军刀Redis其他功能
除了5种数据结构外,Redis还提供了诸如慢查询、Pipeline、Bitmap、HyperLogLog、发布订阅、GEO等附加功能,在这些功能的帮助下,Redis的应用场景更加丰富。
4-1 课程目录
◆慢查询◆Bitmap
◆pipeline◆HyperLogLog
◆发布订阅◆GEO
4-2 慢查询
◆生命周期
◆两个配置
slowlog-max-len:但时间达到slowlog-log-slower-than=10000 之后将会认定为慢查询,随后会进入 长度为slowlog-max-len的队列
slowlog-log-slower-than: 记录为慢查询的阈值
- 慢查询阀值(单位:微秒)
- slowlog-log-slower-than=0,记录所有命令
- slowlog-log-slower-than<0,不记录任何命令。
配置方法
- 默认值
config get slowlog-max-len=128
config get slowlog-log-slower-than=10000 - 修改配置文件重启
- 动态配置
config set slowlog-max-len 1000
config set slowlog-log-slower-than 1000
◆三个命令
1.slowlog get[n]:获取慢查询队列
2.slowlog len:获取慢查询队列长度
3.slowlog reset:清空慢查询队列
◆运维经验
- slowlog-max-len不要设置过大,默认10ms,通常设置1ms
- slowlog-log-slower-than不要设置过小,通常设置1000左右。
- 理解命令生命周期。
- 定期持久化慢查询。
4-3 pipeline
◆什么流水线
使用流水线大大减少网络开销
流水线的作用
两点注意
1.Redis的命令时间是微秒级别(所以速度的瓶颈在网络)。
2.pipeline每次条数要控制(网络)。
◆客户端实现
Jedis jedis =new Jedis("127.0.0.1",6379);
for(int i=0;i<100;i++){
Pipeline pipeline=jedis.pipelined();
for(int j=i*100; j<(i+1)*100; j++){
pipeline.hset("useHashKey:"+j,"field"+j,"value"+j);
pipeline.syncAndReturnAll();
}
}
◆与原生操作(M命令)对比
Pipeline会被拆分 但依然会保证它的原子性
◆使用建议
- 注意每次pipeline携带数据量(数据量过大最好进行拆分)
- pipeline每次只能作用在一个Redis节点上
- M操作与pipeline区别
4-4 发布订阅
◆角色
发布者(publisher)
订阅者(subscriber)
频道(channel)
◆模型
◆API
publish
publish channel message
使用示例:
redis> publish sohu:tv "hello world"
(integer)3 #订阅者个数
subscribe
subscribe [channel] #一个或多个
unsubscribe
unsubscribe [channel]#一个或多个
其他
psubscribe [pattern..…]#订阅模式。
punsubscribe [pattern..…]#退订指定的模式。
pubsub channels #列出至少有一个订阅者的频道。
pubsub numsub [channel..]#列出给定频道的订阅者数量
pubsub numpat #列出被订阅模式的数量
◆发布订阅与消息队列
有了消息队列 的不同是订阅者只能有一个接收到消息 就是在抢夺消息
4-5 bitmap
◆位图
◆相关命令
setbit key offset value
#给位图指定索引设置值
演示:
getbit key offset
#获取位图指定索引的值
bitcount key[start end]
# 获取位图指定范围(start到end,单位为字节,如果不指定就是获取全部)位值为1的个数
bitop op destkey key[key …]
# 做多个Bitmap的and(交集)、or(并集)、not(非)、xor(异或)
# 操作并将结果保存在destkey中
bitpos key targetBit [start] [end]
#计算位图指定范围(start到end,单位为字节,如果不指定就是获取全部) 第一个偏移量对应的值等于targetBit的位置
◆独立用户统计
◆使用经验
1.type=string,最大512MB
2.注意setbit时的偏移量,可能有较大耗时
3.位图不是绝对好。
4-6 hyperloglog
◆新的数据结构?
HyperLogLog
1.基于HyperLogLog算法:极小空间完成独立数量统计。
2.本质还是字符串。
127.0.0.1:6379>type hyperloglog_key string
◆三个命令
pfadd key element [element..J #向hyperloglog添加元素
pfcount key [key..J #计算hyperloglog的独立总数
pfmerge destkey sourcekey [sourcekey..J #合并多个hyperloglog
使用demo
- 添加与获取总数
- 合并多个hyperloglog
◆内存消耗
◆使用经验
- 是否能容忍错误?(错误率:0.81%,如下面的语句执行结果会每次都不一样)
127.0.0.1:6379>pfcount 2016_05_01:unique:ids(integer)
1009838
- 是否需要单条数据?
4-7 geo
◆GEO是什么
应用场景举例:可以依据位置信息 来实现例如微信摇一摇的功能 查看附近的酒店 餐馆等
◆5个城市经纬度
◆相关命令
geo key longitude latitude member
[longitude latitude member..J
#增加地理位置信息
使用案例:
geopos key member [member..…]
#获取地理位置信息
演示:
geodist key member1 member2 [unit]
#获取两个地理位置的距离
#unit:m(米)、km(干米)、mi(英里)、ft(尺)
georadius key longitude latitude radiusm|km|ft|mi [withcoord][withdist]
[withhash] [COUNT count] [asc|desc] [store key][storedist key]
georadiusbymember key member radiusm|km|ft|mi [withcoord]
[withdist] [withhash] [COUNT count] [asc|desc][store key] [storedist key]
#获取指定位置范围内的地理位置信息集合
withcoord:返回结果中包含经纬度。
withdist:返回结果中包含距离中心节点位置。
withhash:返回结果中包含geohash COUNT count:指定返回结果的数量。
ascldesc:返回结果按照距离中心节点的距离做升序或者降序。
store key:将返回结果的地理位置信息保存到指定键。
storedist key:将返回结果距离中心节点的距离保存到指定键
使用示例
◆相关说明
- since3.2+ 版本才会有该功能
- type geokey=zset 数据结构其实是zset
- 没有删除API:zrem key member 可以使用zset的删除语句
5. Redis持久化的取舍和选择
Redis的持久化功能有效避免因进程退出造成的数据丢失问题,本章将介绍介绍RDB和AOF两种持久化配置和运行流程,以及选择策略
5-1 目录
◆持久化的作用
◆RDB
◆AOF
◆RDB和AOF的抉择
5-2 持久化的作用
◆什么是持久化
redis所有数据保持在内存中,对数据的更新将异步地保存到磁盘上。
◆持久化的实现方式
快照
- MySQL Dump
- Redis RDB
写日志
- MySQL Binlog
- Hbase HLog
- Redis AOF
5-3 RDB
◆什么是RDB
◆触发机制-主要三种方式
save 命令(同步)
由于是同步命令 会造成阻塞
执行该命令的文件策略:如存在老的RDB文件,将进行替换
执行该命令的复杂度O(N)
bgsave命令
使用 fork()创建一个子进程来进行RDB的生成 完成后再通知给主进程
其中使用 fork()速度会更快 但是依然有可能阻塞主线程
执行该命令的文件策略和复杂度与save命令相同
sava与bgsave的不同
自动生成RDB
在seconds时间内 发生 changes 次改变则触发生成RDB
实际上改方式无法控制生成RDB的一个频率
配置
save 9001
save 30010
save 6010000
dbfilename dump.rdb #文件名称
dir./ #相关文件存放位置
stop-writes-on-bgsave-error yes # 如果 bgsave发生了错误是否停止写入
rdbcompression yes # rdb文件是否采用压缩格式
rdbchecksum yes #是否对rdb文件进行一个检验
最佳配置(更改相关参数 对于多台机器要对文件名称进行区分 将文件保存在不同的位置)
◆触发机制-不容忽略方式
- 全量复制
- debug reload:进行一个debug级别的重启 不需要将内存进行清空 并且在该过程仍会触发RDB文件的生成
- shutdown : 进行关闭的时候会进行 RDB文件的生成
◆试验
save阻塞
bgsave fork
真的自动?
RDB长啥样?
待做。。。。
RDB总结
- RDB是Redis内存到硬盘的快照,用于持久化。
- save通常会阻塞Redis。
- bgsave不会阻塞Redis,但是会fork新进程。
- save自动配置满足任一就会被执行。
- 有些触发机制不容忽视
5-4 AOF
◆RDB现存问题
- 耗时、耗性能
- 不可控、丢失数据
◆什么是AOF
创建过程中将执行的命令保存在AOF中
重启之后再将AOF载入到Redis当中
◆AOF三种策略
always
always表示每条命令都执行 fsync 学到硬盘中 防止内容丢失
everysec
每秒刷新到硬盘中 可能会丢失一秒的数据
no
由操作系统来决定
三种策略比较
默认使用第二种
◆AOF重写
过期、重复、没有用或可优化的命令 进行化简 从而减少AOP文件
AOF重写作用:
- 减少硬盘占用量
- 加速恢复速度
AOF重写实现两种方式
bgrewriteaof:类似于 Bgsave命令
AOF重写配置
需要同时到达如下配置才能够触发
·aof_current_size>auto-aof-rewrite-min-size
·aof_current_size-aof_base_size/aof_base_size>auto-
aof-rewrite-percentage
◆AOF的配置
appendonly yes # 打开使用aof
appendfilename #"appendonly-${port}.aof" #配置aof的文件名
appendfsync everysec #AOF策略
dir/bigdiskpath
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
◆实验
待做。。。。
5-5 RDB和AOF抉择
◆RDB和AOF比较
◆RDB最佳策略
- “关"
- 集中管理
- 主从,从开?
◆AOF最佳策略
- “开”:缓存和存储
- AOF重写集中管理
- everysec
◆最佳策略
- 小分片
- 缓存或者存储
- 监控(硬盘、内存、负载、网络)
- 足够的内存