keys
dbsize #计算key的总数
exists key #检查key是否存在
del key [key] #删除指定key-value
type key #返回key的类型
expire key seconds #key在seconds过时
ttl key #查看key剩余的过时时间
persist key #去掉key的过时时间
复制代码
kyes基本不在生产环境使用html
keys * #遍历全部key
key [pattern]
复制代码
命令 | 时间复杂度 |
---|---|
keys | O(n) |
dbsize | O(1) |
del | O(1) |
exists | O(1) |
expire | O(1) |
type | O(1) |
单线程须要注意什么?java
keys, flushall, flushdb, slow lua script, mutil/exec, operate big value(collention)
fysnc file descriptor
close file descriptor
复制代码
get key #获取key对应的value O(1)
set key value #设置key-value O(1)
del key #删除key-value O(1)
mset key value key value #批量设置key-value O(n)
mget key key #批量获取key-value O(n)
incr key #key自增1,若是key不存在,自增后get(key)=1 O(1)
decr key #key自减1,若是key不存在,自减后get(key)=-1 O(1)
incrby key k #key自增k,若是key不存在,自增后get(key)=k O(1)
decrby key k #key自减k,若是key不存在,自减后get(key)=-k O(1)
set key value #无论key是否存在,都设置 O(1)
setnx key value #key不存在,才设置 O(1)
set key value xx #key存在,才设置 O(1)
getset key newvalue #set key newvalue并返回旧的value
append key value #将value追加到旧的value
strlen key #返回字符串的长度(注意中文)
incrbyfloat key 3.5 #增长key对应的值3.5
getrange key start end #获取字符串指定下标的全部的值
setrange key index value #设置下标全部对应的值
复制代码
哈希键值结构mysql
hmset key field value field value #批量设置 O(n)
hmget key field field #批量获取 O(n)
hget key field #获取hash key对应的field的value O(1)
hset key field value #设置hash key对应field的value O(1)
hdel key field #删除hash key对应的field的value O(1)
hexists key field #判断hash key 是否有field O(1)
hlen key #获取hash key field的数量 O(1)
hgetall key #h返回hash key对应全部的field和value O(n)
hvals key #返回hash key对应全部field的value O(n)
hkeys key #返回hash key对应全部field O(n)
hsetnx key field value #设置hash key对应field的value(如field存在,则失败) O(1)
hincrby key field intCounter #hash key 对应的field的value自增intCounter O(1)
hincrbyfloat key field floatCounter #hincrby浮点数版 O(1)
复制代码
记录网站每一个用户我的主页的访问量linux
#redis实现
incr userid:pagevies(单线程,无竞争)
hincrby user:1:info pageview count
#java模拟代码
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, transferMapToVideo(videoInfo))
}
}
return videoInfo;
}
复制代码
当心使用hgetall(redis单线程) 例子:如保存一个用户的信息的实现,下面说3种情形,固然还有更多种其余方式ios
命令 | 优势 | 缺点 |
---|---|---|
string v1 | 编程简单,可能节约内存 | 1. 序列号开销 2. 设置属性要操做整个数据 |
string v2 | 直观,能够部分更新 | 1. 内存占用较大 2. key较为分散 |
hash | 直观、节省空间、能够部分更新 | 1. 编程稍微复杂 2. ttl很差控制 |
特色:有序、能够重复、左右两边插入弹出git
rpush key value value ...valueN #从列表右端插入值(1-N个)
lpush key value value ...valueN #从列表左端插入值(1-N个)
linsert key before|after value newValue #在list指定的前|后插入newValue
lpop key #从列表左侧弹出一个item
rpop key #从列表右侧弹出一个item
#根据count值,从列表中删除全部value相等的项
#count > 0,从左到右,删除最多count个value相等的项
#count < 0,从右到左,删除最多Math.abs(count)个value相等的项
#count = 0,删除全部value相等的项
lrem key count value
ltrim key start end #按照索引范围修剪列表 O(n)
lrange key start end #获取列表指定索引范围全部item O(n)
llen key #获取列表长度 O(1)
lset key index newValue #设置列表指定索引值为newValue O(n)
blpop key timeout #lpop阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞 O(1)
brpop key timeout #rpop阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞 O(1)
##小建议-数据结构类比
lpush + lpop = stack
lpush + rpop = queue
lpush + ltrim = capped collection
lpush + brpop = message quere
复制代码
慢查询命令redis
slowlog get [n] #获取慢查询队列
slowlog len #获取慢查询队列长度
slowlog reset #清空慢查询队列
复制代码
1. 默认值
config get slowlog-max-len = 128
config get slowlog-log-slower-than = 1000
2. 修改配置文件重启
3. 动态配置
config set slowlog-max-len 1000
config set slowlog-log-slower-than 1000
复制代码
运维经验sql
批量网络命令通讯模型 编程
命令 | N个命令操做 | 1次pipeline(n个命令) |
---|---|---|
时间 | n次网络 + n次命令 | 1次网络 + n次命令 |
数据量 | 1条命令 | n条命令 |
pipeline-Jedis实现缓存
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
</dependency>
#没用pipeline, 1W次hset须要50s
Jedis jedis = new Jedis("127.0.0.1", 6379);
for(int i=0;i<10000;i++){
jedis.hset("hashkey:"+i,"field"+i, "value"+i);
}
#使用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();
}
复制代码
使用建议
角色 发布者(publisher) 订阅者(subscriber) 频道(channel) 模型
publish channel message #发布消息
subscribe [channel] #一个或多个
unsubscribe [channel] #一个或多个
psubscribe [pattern...] #订阅模式
punsubscribe [pattern...] #退订指定的模式
pubsub channels #列出至少有一个订阅者的频道
pubsub numsub [channel...] #列出给定频道的订阅者数量
pubsub numpat #列出被订阅模式的数量
复制代码
setbit key offset value #给位图指定索引设置值
getbit key offset #获取位图指定索引的值
bitcount key [start end] #获取位图指定范围(start到end,单位为字节,若是不指定就是获取所有)位值为1的个数
bitop key targetBit [start] [end] #计算位图指定范围第一个偏移量对应的值等于targetBit的位置
复制代码
独立用户统计
数据类型 | 每一个userid占用空间 | 须要存储的用户量 | 所有存储量 |
---|---|---|---|
set | 32位(假设userid用的是整型,实际场景不少用长整型) | 50000000 | 32位*50000000=190.7348633MB |
Bitmap | 1位 | 100000000 | 1位*100000000=11.920929MB |
一天 | 一个月 | 一年 | ||
---|---|---|---|---|
set | 200M | 6G | 72G | 大约值 |
Bitmap | 12.5M | 375M | 4.5G | 大约值 |
只有十万独立用户呢?
数据类型 | 每一个userid占用空间 | 须要存储的用户量 | 所有存储量 |
---|---|---|---|
set | 32位(假设userid用的是整型,实际场景不少用长整型) | 100000 | 32位*1000000=0.3814697MB |
Bitmap | 1位 | 100000 | 1位*100000000=0.0119209MB |
使用建议
pfadd key element [element...] #向hyperloglog添加元素
pfcount key [key] #计算hyperloglog的独立总数
pfmerge destkey sourcekey [sourcekey] #合并多个hyperloglog
复制代码
type geoKey = zset
zrem key member
geo key longitude latitude member [longitude latitude member...] #增长地理位置信息
geopos key member [member...] #获取地理位置信息
geodist key member1 member2 [unit] #获取两个地理位置的距离,unit:m、km、mi、ft
复制代码
bgsave
save与bgsave
命令 | save | bgsave |
---|---|---|
IO类型 | 同步 | 异步 |
阻塞 | 是 | 是(阻塞发生再fork) |
复杂度 | O(n) | O(n) |
优势 | 不会消耗额外内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 须要fork,消耗内存 |
# 配置redis.conf
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir ./
stop-write-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
#最佳配置
dbfilename dump-${port}.rdb #指定对应哪一个redis的备份
dir /bigdiskpath #指定具体文件目录
stop-write-on-bgsave-error yes
rdbcompression yes
复制代码
触发机制
RDB总结
RDB有什么问题 耗时、耗性能 不可控、丢失数据
AOF运行原理-建立
AOF的三种策略 always
命令 | always | everysec | no |
---|---|---|---|
优势 | 不丢失数据 | 每秒一次fsync丢一秒数据 | 不用管 |
缺点 | IO开销较大,通常的sata盘只有几百TPS | 丢一秒数据 | 不可控 |
AOF重写
AOF重写2种方式
bgrewriteaof命令
自动
配置名 | 含义 |
---|---|
auto-aof-rewrite-min-size | AOF文件重写须要的尺寸 |
auto-aof-rewrite-percentage | AOF文件增加率 |
统计名 | 含义 |
---|---|
aof_current_size | AOF当前尺寸(单位:字节) |
aof_base_size | AOF上次启动和重写的尺寸(单位:字节) |
自动触发实际(同时知足)
#配置redis.conf
appendonly yes
appendfilename "appendonly-${port}.aof"
appendfsync everysec
dir /bigdiskpath
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
复制代码
AOF重写流程
AOF阻塞问题
如何定位
info Persistence
(没法看到具体时间点)RDB和AOF选择
命令 | RDB | AOF |
---|---|---|
启动优先级 | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 丢数据 | 根据策略决定 |
轻重 | 重 | 轻 |
最佳策略
改善fork
子进程开销与优化
单机有什么问题? 机器故障 容量瓶颈 QPS瓶颈
slaveof ip port
slave-read-only yes
slaveof on one
复制代码
全量复制
部分复制
Redis主从复制和集群配置
配置不一致
规避全量复制
规避复制风暴
主从复制-master宕掉故障处理
Redis 数据结构与内存管理策略(上)
Redis 数据结构与内存管理策略(下)
原理、方法左右开弓,大神带你细解Redis内存管理和优化
redis调整内核参数
Redis安全
redis 热点Key的发现与解决之道
redis4.0之基于LFU的热点key发现机制