一. 先聊点别的

  1. sql & nosql

   sql指关系型数据库,如Oracle,MySQL等,nosql泛指非关系型数据库,如MongoDB,Redis等;SQL数据存在特定结构的表中,而NoSQL则更加灵活和可扩展,存储方式可以是JSON文档,哈希表或其他方式;在sql中必须定义好表和字段结构后才能添加数据,如主键,索引,触发器,存储过程等,表结构虽然可以在定义之后被更新,但是如果有比较大的结构变更的化就会变得比较复杂,在nosql中,数据可以在任何时候任何地方添加,不需要先定义表,nosql也可以在数据集中船舰索引;综上:nosql更加适合初始化数据还不明确或者未定的项目中。

  2. ACID & CAP & BASE

  ACID是指在数据库管理系统中,事务所具有的四个特性:原子性,一致性,隔离性,持久性;

  CAP是指一致性,可用性和分区容错性,CAP理论指这三个要素最多只能实现两个;

  BASE接受最终一致性的理论支持,BasicallyAvalable基本可用,Soft-state软状态/柔性事务,EventuallyConsistency最终一致性;

二. Redis:REmote DIctionary Server(远程字典服务器)

1. 什么是Redis?有什么优点?

  Redis是存储kv数据结构的分布式数据库;

  a. 读写速度快,数据存放在内存中,结构类似于HashMap,HashMap的优势就是查找和操作的时间复杂度是O(1);

  b. 支持丰富的数据类型,包括但不限于String,hash,set,zset,list等;

  c. 具有丰富的特性,可以用于缓存,消息队列,可以对key设置过期时间,到期后自动删除;

  d. 支持数据持久化到硬盘RDB&AOF;

  e. 支持主从复制实现数据备份,可以通过哨兵模式自动选举master;

2. Redis和Memcache有什么区别,为什么能够替代它?

  a. Memcache的值都是简单字符串,Redis支持更为丰富的数据类型;

  b. 虽然都是内存数据库,Redis支持持久化;

  c. Redis使用单核,单进程处理客户端请求,对读写事务响应通过epoll函数包装来做到,在大批量文件操作里使用多路IO复用,memcache多核;

  d. Memcache 只能采用客户端使用一致性哈希实现分布式存储,Redis还支持在服务器端构建分布式存储——redis集群,保证单点故障下数据可用性,支持主从复制模式;

3. Redis是单线程的为什么还这么快?

  a. 数据结构简单,对数据的操作也简单;

  b. 避免了不必要的上下文切换和竞争条件,也不存在多进程或多线程导致的切换消耗CPU,不用考虑各种锁的问题;

  c. 完全基于内存,绝大部分请求是存粹的内存操作,非常快速。数据在内存中类似HashMap,查找和操作的时间复杂度O(1);

  d. 使用多路I/O复用模型,非阻塞IO,多路指多个网络链接的请求,复用是同一个线程;

4. Redis的应用

  a. 高速缓存:合理使用缓存不仅可以加速数据访问速度,而且能有效降低后端数据源的压力,Redis提供了过期时间设置,并且提供了灵活控制最大内存和内存溢出后的淘汰机制;

  b. 排行榜系统:Redis提供列表和有序集合数据结构,合理的使用这些数据结构可以很方便构建各种排行榜系统;

  c. 计数器:使用INCR key可以将key存储的数据+1,如果key不存在,会先初始化为0再+1;

  d. 消息队列系统:发布订阅功能和阻塞队列可以实现基本的消息队列功能;

  e. Session共享:redis+tomcat+nginx;

5. 安装启动及操作

  a. 修改redis.conf,设置后台启动daemonize yes;

  b. redis-server /myredis/redis.conf  启动;

  c. redis-cli -p 6379 链接;

  d. ps -ef | grep redis 看有没有启动;

  e. shutdown 关闭;

  f. select id 切换DB,默认16个DB;

  g. keys * 列出key;

  h. flushdb:删除当前数据库所有key

6. key+五大数据类型及操作

  a. key :   exists kname 有返回1,无返回0;

      move key dbid 把key一道dbid数据库中;

      expire key 设置key的过期时间;

      ttl key 查看key的过期时间, -1 表示永不过期,-2表示已过期;

      type key 查看key类型;

      del key 删除;

  b. String :  set/get/del/append/strlen

       Incr/decr/incrby/decrby 一定是数字;

       getrange/setrange 字符串;

       setex/setnx 设置过期时间/set if not exist;

       mset/mget/msetnx 批量操作;

  c. List: lpush/lpop/rpush/rpop/llen;

     lindex 按索引下标获得元素;

     lrem key N value 删除N个value;

     ltrim key begin end 提取指定范围内的值给key;

     rpoplpush 原列表 目的列表;

     lset key index value;

     linsert key before/after 值1 值2

     空value,key消失;

  d. Set: sadd/smembers/sismember;

     scard 获取集合中的元素;

     strem key value 删除元素;

     srandmember key 随机出几个数;

     spop 随机出栈;

     smove key1 key2 x 将key1中的x移到key2;

     数学集合:sdiff 差集; sinsert交集;sunion并集;

  e. Hash: key对应的value是k-v对;

     hset/ hget/ hmset/ hmget/ hgetall/ hdel/ hlen/ hexists  key/ hkeys / hvalues/ hincrby/

     hincrebyfloat/ hsetnx;

  f. zset: 在set的基础上,加一个score值,k1 score1 v1 score2 v2;

     zadd key s1 v1 s2 v2;

     zrange key 0 -1 (withscore);

     zrem key s1 v1 删除s1 v1;

     zcard/zcount key score区间;

     zscore key 对应值:获得分数;

     zrank key values 获取下标值;

     zrevrank key values 逆序获取下标值;

     zrevrangebyscore key

7. 缓存过期的策略

  a. volatile-lru : 使用LRU移除过期时间的key;

  b. allkey-lru:使用LRU移除任意key;

  c. volatile-random : 过期集合中随机移除key;

  d. allkey-random:随机移除任意key;

  e. volatile-ttl:移除ttl最小的key;

  f. noeviction 永不过期(默认)

8. 持久化

  a. RDB:

  时间段内的数据集快照存入磁盘,恢复直接将快照读取到内存;Redis会单独fork一个子进程来进行持久化,会先将数据写入一个临时文件中,该临时文件用来替换上次持久化好的文件,主进程不进行任何IO操作;

  如果进行大规模数据恢复,但是对数据完整性要求不高,RDB比AOF效率更高;它的缺点是最后一个持久化的数据可能会丢失;

  Fork复制一个于当前进程一样的进程,所有数据都和原进程一样,如果原进程很大,fork后可能放不下;

  RDB保存的是dump.rdb文件,在配置文件中可以设置 save second changes 持久化的频率,例如,save 120 10就表示2分钟内key修改了10次就会触发RDB持久化操作;指向shutdown指令会自自动生成dump.rdb;

  如何触发RDB快照:默认配置;使用命令save(阻塞式)或bgsave(后台操作),flushall也会触发;

  b. AOF(Append only file): 以日志形式记录每一个写操作,只许追加不可改写,redis启动之初会读取该文件重新构建数据;

  appendfsync机制:Always(同步持久化,一旦更改就写入磁盘,性能差,但是完整性好),EverySec(默认,每秒记录,一秒内如果宕机会造成数据丢失),No不执行持久化;

  AOF启动:设置appendonly yes;  

  正常恢复:将有数据的aof文件复制一份保存到对应目录(config get dir),重启redis后重新加载;

  异常恢复:备份被写坏的aof,执行redis-check-aof --fix恢复;

  rewrite:文件追加越来越大,大小超过设定的阈值,内容压缩或删除,保存可恢复的最小指令集,可以使用命令bgrewriteaof;原理是fork一条新的进程将文件重写;触发机制是redis会记录上次AOF的大小。默认是当aof文件大小是上次rewrite后大小的一倍(auto-aof-rewrite-percentage 100)且文件大于64M(auto-aof-rewrite-min-size 64m)时触发;

  AOF与RDB相比相同数据集的数据而言aof文件远大于rdb,恢复速度慢,且aof运行效率低;但是数据更完整;

  c. RDB or AOF? 看需求,RDB在指定时间间隔内对数据进行快照存储,AOF记录每次对服务器写的操作;如果只做缓存,不会持久化;一般同时开启,先加载AOF(更完整),RDB更适合于备份数据库,快速重启,不会有AOF可能存在的bug;

9. Redis事务

  a. 事务:可以一次执行多个命令,本质是一组命令的集合,按序串行执行不会被其他命令插入;使用MULTI开启,输入命令到Queue中,EXEC会执行Q中命令,Discard放弃本次任务执行;watch key [key,...] 监视,事务执行前,key不变,unwatch取消所有key的监视;

10. 消息订阅和发布

  进程间的通信模式:发送者pub发送消息,订阅者sub接收;

  可以一次性订阅多个:subscribe c1 c2 c3;

  消息发布:publish c2 hello-redis;

  订阅多个:通配符 * 例如 psubscribe new*;

11. Redis主从复制

  a. 特性:主机(master:写为主)数据更新后根据配置和策略,自动同步到备机(salves,读为主);读写分离,容灾恢复;配从不配主,从库配置方法:slave of 主库ip 端口;

  b. 原理:slave启动成功链接到master后会发送一个sync命令;Master接到命令会启动后台存盘进程,同时收集所有收到的用于修改数据集的命令,在后台进程执行完毕后,master将传送整个数据文件到slave,已完成一次同步;首次同步使用全量复制,只会采用增量复制;

  c.缺点是延迟,造成不一致;

  d. 可以考虑关闭主服务器数据的持久化功能,只从从服务器进行持久化,从服务器设置为只读模式;

12. 哨兵模式

  心跳机制+投票裁决:每个sentinel会向其他sentinel,master,slave定时发送消息,以确定对方是否活着,如果发现对方在指定时间内未响应,则暂时认为对方挂了;若哨兵群中多数都报告某一master没响应,才认为彻底死亡,然后通过vote算法选出新的mster;

  在sentinel.conf文件中设置sentinel monitor 主机名 ip 端口 1;

  “1”表示主机挂掉后slave投票看谁接替成为主机,投票最多的成为主机;

  启动哨兵:Redis-sentinel /myredis/sentinel.conf;

  一组sentinel可以监视多个Master;

13. 缓存穿透

  指查询一个一定不存在的数据,由于缓存不命中需要从数据库查询你,查不到数据则不写入缓存,导致每次请求该查询都要求数据库查;

  解决:对所有可能查询得的参数以hash形式存储,在控制层先进行校验,不符合则丢弃(布隆过滤器将所有可能存在的数据hash到一个足够大的bitmap中);也可以采用如果一个查询返回的数据为空,仍进行缓存,但过期时间很短;

14.缓存雪崩

  缓存集中在一段时间内失效,发生大量的缓存穿透,所有查询都落在数据库上

  解决:缓存失效后通过加锁或者队列来控制读库写缓存的线程的数量;缓存reload预先更新缓存,在即将发生大的并大访问前手动触发加载缓存;不同的key设置不同的过期时间,让缓存失效的时间点尽量均匀;二级缓存或双缓存策略,A1失效可以访问A2,A1缓存失效时间短,A2长

15. 缓存预热

  系统上线后提前将相关的缓存数据直接加载到缓存系统,避免在用户请求时先查询数据库再将数据缓存;

16. 缓存更新

  除redis自带的6种缓存失效策略,还可以更具具体的业务进行自定义的缓存淘汰:定时清理过期缓存(维护大量缓存的key比较麻烦);用户请求时先判断所用到的缓存是否过期,过期就去底层系统获取数据。

17. Redis实现分布式锁

  在分布式环境下,多个不同的线程需要对共享资源进行同步,那么用java的锁机制就不能实现,这时必须借助分布式锁来解决分布式环境下共享资源的同步问题:redis中提供了一个只有某个key不存在情况下才会设置key值得原子命令setnx,且该命令可以设置过期时间,这样,把获取key的行为当作获取锁,可以保证只有一个线程能够获取到锁且锁会自动过期;但是锁可能在业务执行完成之前过期,所以在设置key的时候,将calue值设置为一个随机的r,释放锁时不直接删除key,而是先getkey判断key对应的value是否等于先前设置的随机值,只有两者相等才删除key,由于是随机值,就不会误释放别的客户端申请的锁了。还有问题?getkey+delkey不是原子操作,还是可能误释放别人的锁,只能使用Lua脚本了,具有原子性。

18. 假如Redis中有1亿个key,其中10w个key以某个固定的已知前缀abc开头,怎么找出来?

  使用keys abc*指令可以扫出指定模式的key列表,但是如给redis正在给线上业务提供服务,keys指令会阻塞线程一段时间(redis单线程),这个时候可以使用scan指令,结果可能会有重复,去重就行,时间较keys长。

19. Redis作异步队列

  一般使用list结构作为队列,rpush生成消息,lpop消费消息,lpop没有消息时,适当sleep一会再重试或者可以使用blpop阻塞式pop;

  能不能一次生产多次消费?使用pub/sub订阅者模式实现1:N的消息队列,缺点是消费者下线,生产的消息会丢失,可以用rabbitmq专业的消息队列;
redis如何实现延迟队列?使用zset,拿时间戳为score,消息内容作为key调用zadd生产消息,消费者用zrangebysocre指令获取n秒之前的数据轮询处理。

20. Redis如何保证一致性?

  a. 为什么会不一致?

  1. 单库情况下,服务层的并发读写,缓存与数据库的操作交叉进行:

    

  虽然只有一个DB,在上述诡异的异常时序下,可能会载入脏数据到缓存:

  1)请求A发起一个写操作,第一步淘汰了cache,这个请求由于各种原因卡在服务层了,如进行大量的业务逻辑计算);

  2)请求B发起一个读请求,先会去读缓存,但是读不到;;

  3)请求B又去读DB,结果读出来的是一个脏数据,然后又把脏数据放到了redis里面;

  4)A卡了很久终于写数据库了,写入了最新的数据,这样,redis和数据库中的数据就不一致了;

  b. 主从同步,读写分离的情况下,读从库读到旧数据:

  

  1)请求A发起一个写操作,第一步淘汰了cache;

  2)请求A写数据库了,写入最新的数据;

  3)请求B发起一个读操作,先去读缓存,没读到;

  4)请求3继续读DB,读的是从库,此时主从同步还没有完成,读出的是脏数据,然后脏数据入缓存;

  5)最后数据库主从同步完成,缓存和数据库就不一致了。

  c. 优化思路:

    i. 总结一下上面出现的问题的原因:单库时服务层在进行1s的逻辑计算过程中,可能读到脏数据到缓存,多库时,在1s中主从同步延迟过程中可能读脏数据到缓存,既然脏数据就是在1s时间间隙中入缓存的,是不是可以在写请求完成后,再休眠1s,再次淘汰缓存,就能将1s内写入的脏数据淘汰掉。

  1. ii. 二次淘汰缓存:
    1. 写请求的步骤由2步升级为3步:先淘汰缓存,然后写数据库,休眠一秒,再次淘汰缓存;
    2. 问题:如果所有的写请求都阻塞1s,会大大降低写请求的吞吐量,增加了处理的时间;
    3. 解决:用一个异步队列timer或者消息总线异步来做这个事情:这样,写请求由2步升级为2。5步:即先淘汰缓存,再写数据库,不再休眠1s,而是往消息总线esb上发送一个消息,发送完了就能立刻返回;然后有一个异步淘汰缓存的消费者,在接收到消息后,asy-expire在1s后淘汰缓存;
    4. 代价是会增加一次缓存的miss;
    iii. 二次淘汰的优化
    1. 业务线的写操作增加了一个步骤,为了保证业务线的代码不动,新增一个线下的读binlog的异步淘汰模块,读取到binlog中的数据,异步淘汰缓存。

Redis来啦~~的更多相关文章

  1. 使用redis构建可靠分布式锁

    关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...

  2. Ignite性能测试以及对redis的对比

    测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...

  3. mac osx 安装redis扩展

    1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis   ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...

  4. Redis/HBase/Tair比较

    KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式    支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...

  5. Redis数据库

    Redis是k-v型数据库的典范,设计思想及数据结构实现都值得学习. 1.数据类型 value支持五种数据类型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有 ...

  6. redis 学习笔记(2)

    redis-cluster 简介 redis-cluster是一个分布式.容错的redis实现,redis-cluster通过将各个单独的redis实例通过特定的协议连接到一起实现了分布式.集群化的目 ...

  7. redis 学习笔记(1)

    redis持久化 snapshot数据快照(rdb) 这是一种定时将redis内存中的数据写入磁盘文件的一种方案,这样保留这一时刻redis中的数据镜像,用于意外回滚.redis的snapshot的格 ...

  8. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

  9. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

  10. windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...

随机推荐

  1. 探索 IPv6 网络

    目录 0x00 前言 0x01 探索 服务器配置 IPv6 地址 服务器部署网络代理 客户端配置网络代理 测试访问 IPv6 地址 给博客添加 IPv6 地址 0x00 前言 IPv4 地址枯竭的事情 ...

  2. 闲来无事写了一套 Jenkins 主题样式:刀锋

    背景 Jenkins 的前端 CSS 样式坚挺了这么多年已经觉得腻的不行了,于是想换个风格缓解一下视觉疲劳,便有了这个项目.由于本人不是前端,所以很多只是随便改改,有些复杂的需求也实现不了,但是总的来 ...

  3. Aso.Net Core 的配置系统Configuration

    目录 Aso.Net Core 的配置系统Configuration 01.Json文件的弱类型方式读取 02.Json文件的强类型获取方式 Aso.Net Core 的配置系统Configurati ...

  4. Java中我常用到的十二个最基本的快捷键

    自己在Java中经常用到的快捷键先记下来方便日后学习之用: 1. Ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间的了.这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按 ...

  5. Mybatis分页插件PageHelper的学习与使用

    目录 中文教程 PageHelper使用 后端程序员都知道,在Web系统中,分页是一种常见的功能,我之前写的分页方法都比较麻烦,移植性也不高,这就很不乐观了.作为一个积极开朗的程序员,怎么能不去了解P ...

  6. Eclipse官方下载步骤

    今天整理Eclipse项目时,发现自己的IDE不能用了,不兼容自己的JDK,于是决定去官网下载一个适合的IDE,由于官网全部都是英文,所以不是太容易找到,于是就想着出一篇博客帮助以后的人更好的更快的下 ...

  7. VLAN实验4(在eNSP上利用单臂路由实现VLAN间路由)

    原理概述: 以太网中,通常会使用VLAN技术隔离二层广播域来减少广播的影响*并增强 网络的安全性和可管理性.其缺点足同时也严格地隔离了不同VLAN之间的任何二层流量,使分属于不同VLAN的用户 不能直 ...

  8. windows下安装python numpy+scipy+matlotlib+scikit-learn等流行库

    (1)请不要直接使用   pip install scikit-learn pip install Numpy pip install Scipy pip install Matplotlib 命令安 ...

  9. 如何解决jpa 要求column 名称单词必须用下划线

    [转]:http://www.jeesns.cn/article/detail/6657 先引出轮子http://blog.csdn.net/54powerman/article/details/76 ...

  10. 小白的springboot之路(三)、集成mybatis与MySQL

    0.前言 mybatis属于半自动的ORM,相比hibernate这种全自动的ORM,兼顾了性能与易用:目前企业项目中,基本都是mybatis的天下:今天就来整合mybatis与MySQL: 1.整合 ...