博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Redis开发与运维》笔记
阅读量:6509 次
发布时间:2019-06-24

本文共 3959 字,大约阅读时间需要 13 分钟。

本笔记来源于《Redis开发与运维》(付磊 张益军著)

初识Redis

单线程面向快速执行场景的内纯数据库

特性

  1. 数据结构:string字符串(位图bitmaps,hyperloglog),hash哈希表,list列表,set集合,zset有序集合
  2. 单线程模型
  3. 持久化方式:RDB,AOF
  4. 主从复制

数据结构 & API

object encoding testObject:查看testObject内部编码

zipXxx:是更加紧凑的数据结构,集合元素总数少(默认512,有序集合zset是128)且所有元素不大时(64 bytes)采用,否则用其他大容量结构

lpush + lpop = stacklpush + rpop = queuelpush + ltrim = 有限集合lpush + brpop = 消息队列 # brpop阻塞方法ttl : time to live # 过期时间spttl # 过期时间 mspersist # 持久化,会消除过期时间set # string set会移除过期时间复制代码

不支持二级数据结构内部元素过期功能

命令 作用域 原子性 支持多个键 使用建议
move Redis实例内部 弃用
dump + restore Redis实例之间 非原子,不用
migrate Redis实例之间 原子,建议使用

单线程架构

命令到达服务端后,按队列依次单线程执行

epoll I/O多路复用提升IO性能

redis快的原因:

  1. 纯内存访问
  2. I/O多路复用:epoll
  3. 单线程避免线程竞争

keys全量遍历键可能导致redis阻塞,可以在从节点上执行,或者使用渐进式的scan代替(可能漏掉期间进行的更新)

附加功能

慢查询分析

慢查询只统计执行命令的时间,并不统计网络通信和命令排队的时间

slowlog-log-slower-than : 0记录所有命令,<0不记录,>0记录超过该阈值的命令(微妙μs),默认10000,并发量100slowlog-max-len : 按列表储存,日志最大数量复制代码

redis shell

--bigkeys : 使用scan命令对键采样,找到内存占用较大的键值--latency/latency-history/dist : 检测网络延迟--stat:实时获取统计信息复制代码

pipeline

将一组redis命令组装,通过一次RTT(Round Trip Time往返时间)传输给Redis,再将执行结构一次性按序返回

pipeline非原子操作

事务与Lua

事务

watch key # 此代码后到事务执行前,key没有被其他客户端修改过才执行事务multicmd...execdiscard #停止事务复制代码

命令写错了,不执行事务 运行时错误,已执行的不回滚,redis不支持事务回滚

Lua

Lua脚本为原子执行

eval:执行lua脚本 eval 脚本内容 key个数 key列表 参数列表

evalsha:服务器复用脚本 evalsha 脚本SHA1值 key个数 key列表 参数列表
script kill:杀掉正在执行的Lua脚本

bitmaps

bitmaps本质上是字符串,不是一种数据结构

HyperLogLog

HyperLogLog本质上是字符串,不是一种数据结构

可以利用极小的内存空间完成独立总数的统计

近似估计,有失误率,用精度换取空间

Redis阻塞

  1. 定位异常节点

    可以修改客户端connection类,专门捕获连接,发送命令和协议读取事件的异常,打印出对应的ip port,定位阻塞节点

  2. 排查内在原因

    API或数据结构使用不合理 CPU饱和 与持久化相关的阻塞

redis内存

哨兵 sentinel

客户端在初始化时是连接sentinel集合获取master节点信息

sentinel节点之间可以共享数据

sentinel可以同时监控多个主节点

  1. 每个sentinel会对数据节点和其他sentinel节点进行监控,发现节点不可达时,对节点做下线标识
  2. 被下线标识的是master节点,则sentinel会和其他sentinel节点协商,当大部分sentinel节点认为master节点不可达,就选举出一个sentinel节点完成故障自动转移

leader sentinel选举(Raft算法):任何一个sentinel确认主节点主观下线后,立即向其他所有sentinel节点发送投票命令(设置发送方sentinel为leader),其他节点未同意的才能同意请求,否则拒绝,当至少有max(quorum,sentinels/2+1)个sentinel节点同意成立,否则进行下一次选举

类似zookeeper leader选举,本质上都是多数投票,未选出结果就多轮投票

# sentinel.conf# sentinel节点配置了master节点信息,会从master节点获取其他slave节点信息# 2: 1)至少2(quorum)个sentinel认为主节点不可达,才可以判定不可达#    2)至少有max(2,sentinels/2+1)个节点参与选举,才能选出leader sentinelsentinel monitor master-1 10.211.55.10 6381 2# 每个sentinel ping其余所有sentinel节点和数据节点,超时5000ms则判定节点失效sentinel down-after-milliseconds master-1 5000# 故障转移超时时间18ssentinel failover-timeout master-1 18000# 添加主节点密码,防止无法监控sentinel auth-pass master-1 test123# 每次故障转移,限制每次2个slave节点向新master节点发起复制,减少对master机器影响sentinel parallel-syncs master-1 2复制代码

tips

  1. sentinel节点不应该部署到同一个机器上
  2. 奇数个sentinel节点

集群

槽是redis集群管理数据的基本单位

集群模式下只有处理槽的主节点才负责读写请求和集群槽等关键信息维护.而从节点只进行主节点数据和状态信息复制

Tips

redis实现分布式锁

前提:redis单线程执行

string的setnx和setxx命令:setnx键必须不存在才能设置成功,setxx键必须存在才能设置成功

public class RedisTool {    private static final String LOCK_SUCCESS = "OK";    //setnx如果已有key存在,则函数不会调用成功    private static final String SET_IF_NOT_EXIST = "NX";    private static final String SET_WITH_EXPIRE_TIME = "PX";    private static final Long RELEASE_SUCCESS = 1L;    /**     * 加锁     */    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {        //requestId:让加锁和解锁是同一个客户端        //设置过期时间,即使客户端崩溃也可解锁,防止死锁        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);        if (LOCK_SUCCESS.equals(result)) {            return true;        }        return false;    }    /**     * 释放分布式锁     */    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {        //Lua脚本:获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁(解锁)        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";        //eval()方法可以确保原子性        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));        if (RELEASE_SUCCESS.equals(result)) {            return true;        }        return false;    }}复制代码

参考链接

转载地址:http://prbfo.baihongyu.com/

你可能感兴趣的文章
AJAX的get和post请求原生编写方法
查看>>
WebSocket 是什么原理?为什么可以实现持久连接
查看>>
Python自学笔记-logging模块详解
查看>>
IE6下实现min-height
查看>>
Nginx服务状态的监控
查看>>
centos各分区用途
查看>>
Head First--设计模式
查看>>
iOS之CAGradientLayer属性简介和使用
查看>>
微信小程序UI组件、开发框架、实用库
查看>>
正则表达式
查看>>
模块化Javascript代码的两种方式
查看>>
Money去哪了- 每日站立会议
查看>>
Python数据结构和算法学习笔记1
查看>>
正则之从dom字符串中提取url
查看>>
大数据——基础概念
查看>>
第六次上机实验
查看>>
机器学习温和指南
查看>>
解决Geoserver请求跨域的几种思路,第二种思路用过
查看>>
最短路-Bellman-Ford算法
查看>>
Object 类有哪些方法
查看>>