有时候须要将原先存有的大量数据迁移到新的redis实例,redis提供一些方案可让这个过程更快linux
经过redis-cli一个一个操做太慢redis
经过pipeline操做,又会阻塞服务器算法
大数据量插入时,先按官网提到的协议生成对应格式的文本文件,而后使用redis-cli的管道模式批量导入缓存
将数据分布到不一样的redis实例安全
范围分片: 例如根据用户id的区间决定数据划分到哪一个实例服务器
hash分片: 先使用哈希函数求得哈希值,再经过取模根据结果例如介于0-3之间决定数据存储在哪一个实例.少数客户端在这基础上实现了连续哈希网络
客户端分片: 在客户端就决定好读写的实例数据结构
代理分片: 客户端发送请求到代理,由代理决定实际的redis实例并返回响应给客户端,例如Twemproxy就应用这种模式异步
查询路由: 客户端发送请求到随机的一个redis实例,redis再转发请求到正确的节点.Redis Cluster 使用了这种模式,不一样的是将客户端的链接重定向到正确的redis实例上而不是直接转发.分布式
分片后,不能直接对多个key一次操做
事务不能对多个key操做
像有序集合数据集被包含在一个大key中没法对内部key进行分片
增长操做复杂度,例如备份数据,须要整合各个实例的持久化文件
增长或减小容量比较复杂,Redis Cluster会从新平衡数据,当增长或者移除节点时.而使用客户端或代理分片方式则难以作到,Pre-sharding技术经过迁移实例的方式实现
已经有多种库实现了分布式redis锁管理,具体https://redis.io/topics/distlock
安全性: 互斥,同一个时刻只能有一个客户端拥有锁
死锁的释放: 例如当客户端锁住资源发生崩溃而其余客户端获取锁时
故障容错: 只要大部分redis节点存活,客户端就能进行正常的获取释放锁
客户端A从主库获取对资源a的锁
对key的写入发送到从库前,主库崩溃
从库被提高为主库
客户端B从主库获取对资源a的锁,此时就违背了安全性原则
使用setnx设置key的值,值必须全局惟一,释放锁时检查key是否存在,值是否与预期一致(第二条解释)
当客户端获取的锁的key带有过时时间.直接使用del最后释放锁的方式,若是过程当中由于一些耗时操做致使key过时,此时其余客户端可以获取到锁,则最后del释放锁会把其余客户端的锁也释放.因此经过设置锁key的值做为签名并在最后使用del释放时作检查
使锁key的值惟一可使用rc4根据具体信息生成对应随机字符串
假设有5个redis独立主库
客户端先获取当前的时间毫秒级
顺序获取5个实例的锁,一样的key名和随机值.
客户端获取锁时,会设置一个相对锁过时时间很小的超时时间,若是一个实例获取不到锁超时则马上获取下一个实例的
顺序获取实例锁时,锁的有效时间会逐渐递减,以最后获取实例的锁有效时间为准,最后每一个实例锁的过时时间会是一致
若是已经存在N/2+1实例的锁key或者锁过时,则放弃获取全部实例的锁的操做.这就能够实现互斥原则,当一个客户端获取成功后,其余客户端能够由于没有获取到足够实例的锁而放弃
该算法基于假设全部机器和进程的时钟频率一致或相对于锁过时时间产生的偏差能够忽略不计
当获取锁失败时,须要及时释放已获取的部分实例锁,能够避免须要等到key过时才能再次获取锁
文档对安全性和可用性进行了讨论,具体能够看文档
提升锁的性能能够经过使用非阻塞模式发送全部命令,再读取检查
须要设置持久化参数fsync=always避免断电或其余灾难后重启key丢失问题
算法对于断电或灾难重启后的实例再也不参与现有活跃的锁.若是客户端A获取到3/5实例锁,而重启新增了一个实例,此时存在N/2+1实例的锁key条件不存在,其余客户端又能够获取锁了.解决问题的方法时,重启后保持一段不可用时间大于其余锁的过时时间.这里会引入一个问题就是若是多个实例重启,在这个不可用期间,意味着新的获取锁可能失败.
扩展能够考虑可重入锁的实现
key空间报告经过发布订阅模式实现,默认不开启,能够经过配置文件开启
接收对key产生实际操做的事件
redis主要经过key来获取数据,利用redis的一些数据结构能够建立二级索引
经过有序集合的分值对数据对象进行索引
常见的操做为,hash结构存储数据对象集合,有序集合对数据对象建立索引
若是能将多维数据转为线性,则能够利用有序集合对数据进行list索引
两个分值同样的,则经过C函数memcmp比较
ZRANGEBYLEX能够对值进行检索,包括或排除,能够利用在自动补全场景
能够再给值加上频率条件
考虑大小写条件时,能够按小写:频率:大写的方式存储值
使用组合索引,实际就是将多个字段信息组合后存储为有序集合
只要找到一种规则就能够合理利用ZRANGEBYLEX对数据进行查询
主库发送将命令实时发送给从库
主从链接断开时会重连,并找回链接断开期间主库命令从新同步
若是找回断开期间部分的命令失败,则执行所有同步,具体由主库发送快照给从库,而后继续保持同步
从库复制异步进行,从库返回确认也是异步进行
若是从库落后主库,能够根据配置决定此时从库是否还可使用旧的数据
主从复制的一个好处是能够避免主库持久化老是须要将数据写入磁盘,能够经过从库复制实时保存.然而须要注意的是,若是重启主库,主库数据集为空,从库同步复制主库时,从库数据也会被清空
建议在主从都开启持久化,或者若是不开启持久化则要避免重启机器后自动重启服务
每个主库有一个replication id标识,对每一个发送给从库的命令会有一个下标.若是从库断连后重连,则会告诉主库最后一个下标,并从该下标开始追赶执行命令同步主库
重新同步时,主库会开启一个存储进程生成RDB文件(写入磁盘),并缓存新接收的写命令.将RDB文件发送给从库,从库加载RDB文件到内存中,并接收主库缓存的命令而后继续同步
从库不会对key作expire操做,当主库key过时时执行del操做时发送到从库,从库执行
当访问从库已过时key时,由于主库的延迟操做,从库根据自身时钟作出判断报告该key不存在
主库执行Lua脚本时,时间被冻结,因此脚本必须同步到从库执行保证一致效果
RDB: 经过对某个时间点数据集存储为快照文件
AOF: 记录每个写操做,经过重放方式初始化数据
能够在同一个实例中同时使用这两种模式,重启实例时,AOF模式用于重新初始化数据
为所欲为对某个时间点的数据进行备份
适合用于灾难恢复
经过子进程完成备份,而父进程不用磁盘IO,不影响其余命令的进行
重启初始化数据更快
派生子进程,在数据集很大时会比较耗时.频繁备份对性能有必定损耗
能够多种文件同步策略,每秒记录或每一个写命令时记录,持续性更好
是一个只加文件,无需定位,容易修复
若是AOF文件太大时,redis会自动生成新的文件并切换到新的文件
若是不当心执行了FLUSHALL命令,只要尚未新的命令写入,中止实例.并将最后一个命令删除后重启redis就能够了
redis会避免RDB和AOF的进程在同一时刻进行
建议设置定时任务生成每一个小时的RDB文件放在一个文件夹和生成天天的RDB文件放在另外一个文件夹
定时任务每次执行,清除比较老的RDB文件
天天转移RDB文件
网络安全策略,将redis运行在虚拟化的linux实例避免直接暴露,外部没法经过防火墙链接redis,客户端经过环回地址与对应端口通讯
安全模式: 从3.2.0版本开始,若是在配置上容许绑定全部端口,并且外部访问无需密码时会进入安全模式,只有经过环回地址的才可以正常访问,其余的客户端返回错误
认证功能: 密码应该设置足够长
数据加密: redis并不支持,不过能够再加一层SSL代理.redis推荐Spiped作对称加密
设置一些命令不可用
NoSQL注入: 注意从不可信赖来源获取可能为Lua脚本做为字符串的问题