Redis杂谈
目录
redis典型应用场景
一、缓存系统
例如,缓存视频的基本信息
public VideoInfo get(long id) {
String redisKey = redisPrefix + id;
Map<String, String> hashMap = redis.hgetAll(redisKey);
VideoInfo videoInfo = transferMapToVideo(hashMap);
if (videoInfo == null) {
videoInfo = mysql.get(id);
if(videoInfo != null) {
redis.hmset(redisKey, transferVideoToMap(videoInfo));
}
}
}
redis存储用户信息的三种方式:
1、String类型,value存储json串
2、String类型,很多个key,每个key对应一种属性
3、Hash类型,设置一个key,将filed存储为属性,value为对应的值。
方式比较:
命令 | 优点 | 缺点 |
string v1 | 编程简单 可能节约内存 | 1、序列化开销 2、设置属性要操作整个数据 |
string v2 | 直观 可以部分更新 | 1、内存占用较大 2、key较为分散 |
hash | 直观 节省空间 可以部分更新 | 1、编程稍微复杂 2、ttl不好控制 |
二、计数器
incr (单线程:无竞争)
记录网站每个用户个人主页的访问量?(用hash,例如: hincrby user:1:info pageview count)
三、消息队列系统
blpop brpop
blpop key timeout #lpop阻塞版,timeout是阻塞超市时间,timeout=0永远不阻塞, 时间复杂度O(1)
1、LRUSH + LPOP = Stack
2、LPUSH + RPOP = Queue
3、LPUSH + LTRIM = Capped Collection (控制获取列表的大小)
4、 LPUSH + BRPOP = Message Queue (消息队列)
四、排行榜
五、分布式锁
set:无论key是否存在都插入成功
setnx: 当key不存在时才插入成功
set xx: 当key存在时才插入覆盖成功
数据结构和内部编码
redis为什么读写速度很快?
1、纯内存
2、非阻塞IO
3、单线程(避免线程切换和竞态消耗)
慢查询
生命周期:
两点说明:
1)慢查询发生在第3阶段
2)客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素(跨机房访问)
两个配置
slowlog-max-len
1、先进先出队列
2、固定长度
3、保存在内存内
slowlog-log-slower-than
1、慢查询阀值(单位:微妙)
2、slowlog-log-slower-than=0,记录所有命令
3、slowlog-log-slower-than<0,不记录所有命令
1)默认值
config get slowlog-max-len = 128
config get slowlog-log-slower-than = 10000
2)修改配置文件重启
3)动态配置
config set slowlog-max-len 1000
config set slowlog-log-slower-than 1000
三个慢查询命令
1、slowlog get [n] : 获取慢查询队列
2、slowlog len : 获取慢查询队列长度
3、slowlog reset: 清空慢查询队列
运维经验
1、slowlog-max-len不要设置过大,默认10ms,通常设置1ms (跟qps有关)
2、slowlog-log-slower-than不要设置过小,通常设置1000左右
3、理解命令生命周期
4、定期持久化慢查询(遇到问题,对以往的慢查询命令进行分析解决问题很有帮助)
pipeline
1次网络命令通信模型
1次时间 = 1次网络时间 + 1次命令时间
什么是流水线
1次pipeline(n条命令) = 1次网络时间 + n次命令时间
注意: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("hashkey:" _ j, "field" + j, "value" + j);
}
pipeline.syncAndReturnAll();
}
3、与原生M操作相比?
pipeline(非原子性的,会进行拆分)
mset、mget这些(原子性的执行)
4、使用建议:
1)注意每次pipeline携带数据量;
2)pipeline每次只能作用在一个Redis节点上
3)M操作与pipeline区别
发布订阅
1、角色
发布者(publisher)、订阅者(subscriber)、频道(channel)
2、模型
3、API
publish channel message #发布
unsubscribe [channel] #取消一个或者多个订阅
subscribe [channel] #一个或者多个订阅
psubscribe [pattern...] #订阅模式
punsubscribe [pattern...] #退订制定的模式
pubsub channels #列出至少有一个订阅者的频道
pubsub numsub [channel...] #列出给定频道的订阅者数量
pubsub numpat #列出被订阅者模式的数量
4、发布订阅与消息队列
LPUSH + BRPOP = Message Queue (消息队列)
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、使用set和Bitmap
2、1亿用户,5千万独立
数据类型 | 每个useridzhan占用空间 | 一天需要存储的用户量 | 全部内存量 |
set | 32位(假设userid用的是整数,实际很多网站用的是长整型) | 50,000,000 | 32位*50,000,000=200MB |
Bitmap | 1位 | 100,000,000 | 1位 * 100,000,000=12.5MB |
只有10万独立用户呢(因为bitmap得占有全部的用户数)
数据类型 | 每个useridzhan占用空间 | 一天需要存储的用户量 | 全部内存量 |
set | 32位(假设userid用的是整数,实际很多网站用的是长整型) | 1,000,000 | 32位*1,000,000 = 4MB |
Bitmap | 1位 | 100,000,000 | 1位 * 100,000,000=12.5MB |
使用经验
1、type = string, 最大512MB
2、注意setbit时的偏移量,可能有较大耗时
3、位图不是绝对好
HyperLogLog
1、极小空间完成独立数量统计,是一个数学算法
2、本质还是字符串
3、3个命令
pfadd key element [element...]:向hyperloglog添加元素
pfcount key[key...] : 计算hyperloglog的独立总数
pfmerge destkey sourcekey [sourcekey ...] : 合并多个hyperloglog
4、使用经验
错误率:0.81%
无法取出单条数据
GEO
GEO(地理信息定位):存储经纬度,计算两地距离,范围计算等
5个城市经纬度
北京: 116.28, 39.55 beijing
天津: 117.12, 39.08 tianjin
石家庄: 114.29 38.02 shijiazhuang
唐山: 118.01, 39.38 tangshan
保定: 115.29 38.51 baoding
应用场景:
相关命令
geoadd key longitude latitude member [longitude latitude member ...] #增加地理位置信息
例如:
geoadd cities:locations 116.28 39.55 beijing
geopos key member [member] #获取地理位置信息
例如: geopos cities:locations beijing
geodist key member1 member2 [unit] #获取两地地理位置的距离,unit:m(米)、km(千米)、mi(英里)、ft(尺)
例如:geodist cities:locations tianjin beijing km
georadius key longitude latitude radiusm|km|ft|mi #获取指定位置范围内的地理位置信息集合
相关说明
1、since 3.2+
2、type geoKey = zset
3、没有删除API: zrem key member