注:Redis命令参考 http://redisdoc.com/geo/georadius.html
Redis入门
五种基础数据类型及常用命令:
String:set、get、del
- 单个数据存储,最大512M
- 存储的是字符串,如果都是数据可以当数字使用,但是是字符串类型
setnx key value | 如果key不存在添加,存在则不做任何操作 |
setex key seconds value | 设置key并设置生存时间秒 |
getset key value | 返回key旧值并设置新值 |
append key value | 为key追加值,如果不存在直接设置 |
incr key | 自增 |
decr key | 自减 |
Hash:hset、hget、hgetall、hdel
- 一个存储空间保存多个键值对数据
- 底层使用哈希表结构实现数组存储
- 如果field(键)多则使用hashmap结构存储
hexists key field | 检查key中是否存在指定field |
hstrlen keyfield | 返回key中指定field的value长度 |
hkeys key | 返回key中所有key |
hvals key | 返回key中所有value |
hincrby key field increment | key中指定field的value增加指定值 |
List:lpush、rpush、lrange、lpop、rpop
- 存储多个数据,并对数据进入存储空间的顺序进行区分
- 底层使用双向链表存储结构实现
rpoplpush source destination | 获取并移除source列表头数据,并把移除的数据添加到destination列表中 |
llen key | 返回列表长度 |
ltrim key start stop | 保留指定区域数据,其余删除 |
blpop/brpop key timeout | 规定时间内获取并移除数据 |
Set:sadd、smembers、srem
- 存储多个数据,并提供高效查询
- 与hash存储结构完全相同,仅使用field(键),所有的value(值)设置nil
srandmember key count | 随机获取key中指定数量的数据 |
spop key | 随机获取key中指定数量的数据并移除 |
smove source destination member | 将member数据从source移动到destination中 |
sinter key key2 | 获取多个key集合的交集 |
sunion key key2 | 获取多个key集合的并集 |
sdiff key key2 | 获取多个key集合的合集 |
sinterstore destination key key2 | 获取多个key集合的交集并存储到destination集合中 |
sunionstore destination key key2 | 获取多个key集合的并集并存储到destination集合中 |
sdiffstore destination key key2 | 获取多个key集合的合集并存储到destination集合中 |
Sorted Set:zadd、zrange、zrevrange、zrem
- 存储多个数据,并关联一个double类型的分数对数据进行排序
- 在set的存储结构基础上添加一个double类型可排序字段
zrangebyscore key min max [withscores] [limit] | 按条件获取数据 |
zrevrangebyscore key min max [withscores] | 按条件获取数据 |
zremrangebyrank key start stop | 按条件删除数据 |
zremrangebyscore key min max | 按条件删除数据 |
zinterstore destination numkeys key [key] | 获取多个集合交操作并存储到destination集合中 |
zunionstore destination numkeys key [key] | 获取多个集合并操作并存储到destination集合中 |
zrank key member | 获取数据排名位置 |
zscore key member | 修改score值 |
key通用操作
del key | 删除指定key |
exists key | 判断指定key是否存在 |
type key | 获取指定key的数据类型 |
expire key seconds | 为指定key设置有效期(秒) |
ttl key | 获取key的有效期(秒) |
persist key | 将key从时效性转换成永久性 |
keys pattern | 查询key(* 匹配所有 ? 匹配任意一个字符 [abc] 配置abc任意一个字符) |
rename key newkey | key改名 |
sort key | 排序 |
db操作
select index | 切换数据库 |
move key index | 移动key到指定数据库中 |
flushdb | 清空当前数据库 |
flushall | 清空所有数据库 |
Redis高级
Redis持久化
RDB(快照)
- save:加入到任务执行队列中,会阻塞redis服务器
- bgsave:后台调用fork函数生成子进程来完成
AOF(操作过程)
- always:每次写操作均同步到AOF文件中,数据零误差,性能低
- everysec:每秒将缓存区中的写操作同步到AOF文件中,数据准确率较高,性能较高
- no:由系统控制,整体过程不可控
优缺点
- RDB恢复数据比AOF快很多
- RDB存储数据量大,效率低,数据量越大效率越低
- RDB根据某个时间点数据快照进行备份,无法做到实时持久化,具有较大可能性丢失数据
- bgsave每次运行都要执行fork函数生成子进程,会牺牲掉一些性能
- Redis从多版本中RDB文件格式格式未进行统一,可能各服务器版本数据无法兼容
- AOP文件存储体积较大,恢复慢
持久化方式 | RDB | AOF |
占用存储空间 | 小(压缩) | 大(重写) |
存储速度 | 慢 | 快 |
恢复速度 | 快 | 慢 |
数据安全性 | 会丢失数据 | 依策略决定 |
资源消耗 | 高/重量级 | 低/轻量级 |
启动优先级 | 低 | 高 |
事务
事务中单条命令保证原子性,但事务不保证原子性
事务过程中发生编译时异常,结束事务,所有命令不执行
事务过程中发生运行时异常,继续执行,不管报错命令,继续执行其它命令
multi | 开启事务 |
exec | 结束事务 |
discard | 取消事务 |
锁
watch key [key2 ..] | 对指定key添加监控锁,如果key在执行exec前发生变化则事务终止 |
unwatch | 取消对所有key的监控(乐观锁) |
setnx | 设置一个公共锁(悲观锁) |
删除策略
定时删除
- 创建一个定时器,当key设置有过期时间并且过期时间达到时,由定时器立即执行对键的删除操作
- 节约内存,过期就删,快速释放掉不必要的内存占用,但CPU压力大,会影响redis服务器响应时间及吞吐量
- 用CPU性能换存储空间(以时间换空间)
惰性删除
- 数据过期不做处理,下次访问时如果数据过期再删除
- 节约CPU性能,内存压力大,出现长期占用内存的数据
- 用存储空间换CPU性能(以空间换时间)
定期删除
- 周期性轮循redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度
- CPU性能占用设置有峰值,检测频度可自定义设置
- 内在压力不是很大,长期占用内存的冷数据会被持续清理
- 周期性抽查存储空间(随机抽查、重点抽查)
逐出算法
- 检测易失数据(可能会过期的数据)
- volatile-lru:挑选最近最长时间没有被使用的数据淘汰
- volatile-lfu:挑选最近使用次数最少的数据淘汰
- volatile-ttl:挑选将要过期的数据淘汰
- volatile-random:任意选择数据淘汰
- 检测全库数据
- allkeys-lru:挑选最近最长时间没有被使用的数据淘汰
- allkeys-lfu:挑选最近使用次数最少的数据淘汰
- allkeys-random:任意选择数据淘汰
- 放弃数据驱逐
- no-enviction:禁止驱逐数据(redis4.0默认策略)
高级数据类型
bitmaps:存储状态(非黑即白),
bitcount key [start] [end] | 计算给定字符串中,被设置为 1 的比特位的数量 |
bitpos key bit [start] [end] | 返回位图中第一个值为 bit 的二进制位的位置 |
bitpos op destkey key [key] | 对一个或多个保存二进制位的字符串 key 进行位元(交并非异或)操作,并将结果保存到 destkey 上 |
HyperLogLog:统计不重复数据数量
pfadd key element [element] | 将任意数量的元素添加到指定的 HyperLogLog 里面 |
pfcount key [key] | 返回储存在给定键的 HyperLogLog 的近似基数 |
pfmerge destkey sourekey [sourekey] | 将多个 HyperLogLog 合并(merge)为一个 HyperLogLog(并集) |
geo:地理位置
geoadd key longitude latitude member | 将给定的空间元素(纬度、经度、名字)添加到指定的member里面 |
geopos key member [member] | 从member里面返回所有给定位置元素的位置(经度和纬度) |
geodist key member1 member [unit] | 返回两个给定位置之间的距离 |
Redis集群
主从复制
作用:读写分离、负载匀衡 、故障恢复、数据冗余
流程
- 建立连接
- 设置master的地址和端口,保存master信息
- 建立Socket连接
- 发送ping命令
- 身份验证
- 发送slave信息
- 同步数据
- slave请求同步数据
- master创建RDB同步数据并返回给slave
- slave接收RDB同步数据并恢复(全量复制,步骤2之前的数据)
- slave请求部份同步数据(增量复制,步骤2之后的数据)
- master返回复制缓冲区中的命令信息
- slave接收并执行master缓冲区中的命令指令
注:增量复制时使用的三个核心
服务器运行id(runid):每个服务器每次运行都会生成一个运行id,是服务器的身份识别码
主服务器复制缓冲区:主服务器传播命令指令给从服务时会将命令转换成AOF文件数据格式复制一份到缓冲区中
主从服务器偏移量(offset):从服务器请求部份同步数据时对照offset是否在缓冲区中,如果在则主服务器返回该offset后所有指令数据
- 命令传播
- 心跳机制
master默认每10秒(配置repl-ping-slave-period设置)ping一次slave判断从服务器是否存在
slave每秒replconf ack offset一次master汇报自己的偏移量并获取最新数据变更指令
- 断网现象
闪断闪连(忽略)
短时间网络中断(增量复制)
长时间中断(全量复制)
主从常见问题
1. master重启所有slave都将进行全量复制操作
2. 网络环境不佳,出现网络中断,slave不提供服务
3. master的CPU占用过高或slave频繁断开连接
4. 多个slave获取相同数据不同步
哨兵模式
注:哨兵也是一台redis服务器,但不提供数据服务,哨兵通常只配单数
作用
- 监控:不断监测master和slave是否正常运行
- 通知:当监控的服务器出现问题,通知其他哨兵和客户端
- 故障转移:断开master与slave连接,选择一个slave作为master,将其他slave连接新的master并告知地址及端口
流程
- 哨兵发现服务器ping不通
- 通知所有其他哨兵出问题的服务器
- 其他哨兵ping出问题的服务器
- 如果超过半数哨兵确认服务器掉线则断开问题服务器,并通知所有客户端
Redis集群
作用
- 分散单台服务器的访问压力,实现负载均衡
- 分散单台服务器的存储压力,实现可扩展性
- 降低单台服务器宕机带来的业务灾难
数据存储设计
- 通过算法设计计算出key的存储位置
- 所有存储空间切割成16384份,每台主机保存一部份
- 按照key计算出的结果放到对应存储空间中
集群内部通讯设计
- 各个数据库相互通讯,保存各个库中保存的存储空间编号
- 保存key时如果第一次没有访问到指定存储空间所在的数据库时,获取其他库的存储空间编号再直接存储
- 一次未命中,获取获取具体位置,直接存储
经典企业级解决方案
缓存预热
现象:redis服务器启动后快速宕机
问题:redis重启后内部没有数据,所有的数据请求直接到达数据库给服务器带来压力,导致redis服务器宕机
解决:服务器启动时自动缓存热数据或服务器启动之后手动加载热数据
缓存雪崩
现象:数据库连接量激增,直接导致数据库崩溃
问题:较短时间内大量缓存集中过期,在此期间请求访问过期数据未命中,redis向数据库获取数据
解决:构建多级缓存、限流降级(短时间内限制一部份请求访问)、缓存过期时间分散设置、删除策略设置LFU(按命中次数删除)
缓存击穿
现象:数据库连接量激增,直接导致数据库崩溃
问题:redis某个key过期,该key访问量巨大,redis短时间向数据库发起对同一数据的访问导致数据库崩溃
解决:超热数据设置永久(不过期)、构建多级缓存、加锁
缓存穿透
现象:数据库连接量持续增加,数据库服务器压力激增,导致数据库崩溃
问题:出现非正常URL访问,大量请求数据库不存在的数据,redis未命中后访问数据库,导致数据库崩溃
解决:设置临时缓存null、白名单策略
性能指示监控