最新面试题-数据库和缓存

目录

1、列举常见的关系型数据库和非关系型数据库都有那些?


关系型数据库:Oracle、Microsoft SQL Server、MySQL、DB2、Microsoft Access
非关系型数据库:NoSql、Cloudant、MongoDb、redis、HBase 

关系型数据库
  关系型数据库的特性:

  1、关系型数据库,是指采用了关系模型来组织数据的数据库;
  2、关系型数据库的最大特点就是事务的一致性;
  3、简单来说,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。

  关系型数据库的优点

  1、容易理解:二维表结构是非常贴近逻辑世界一个概念,关系模型相对网状、层次等其他模型来说更容易理解; 
  2、使用方便:通用的SQL语言使得操作关系型数据库非常方便; 
  3、易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率; 
  4、支持SQL,可用于复杂的查询。

  关系型数据库的缺点

  1、为了维护一致性所付出的巨大代价就是其读写性能比较差; 
  2、固定的表结构; 
  3、高并发读写需求; 
  4、海量数据的高效率读写;

非关系型数据库
  非关系型数据库的特性

  1、使用键值对存储数据; 
  2、分布式; 
  3、一般不支持ACID特性; 
  4、非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合。

  非关系型数据库的优点

  1、无需经过sql层的解析,读写性能很高; 
  2、基于键值对,数据没有耦合性,容易扩展; 
  3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。

  非关系型数据库的缺点

   1、不提供sql支持,学习和使用成本较高; 
   2、无事务处理,附加功能bi和报表等支持也不好;

2、MySQL常见数据库引擎及比较?


MyISAM

特性
不支持事务:MyISAM存储引擎不支持事务,所以对事务有要求的业务场景不能使用
表级锁定:其锁定机制是表级索引,这虽然可以让锁定的实现成本很小但是也同时大大降低了其并发性能
读写互相阻塞:不仅会在写入的时候阻塞读取,MyISAM还会在读取的时候阻塞写入,但读本身并不会阻塞另外的读
只会缓存索引:MyISAM可以通过key_buffer缓存以大大提高访问性能减少磁盘IO,但是这个缓存区只会缓存索引,而不会缓存数据

适用场景
不需要事务支持(不支持)
并发相对较低(锁定机制问题)
数据修改相对较少(阻塞问题)
以读为主
数据一致性要求不是非常高

最佳实践
尽量索引(缓存机制)
调整读写优先级,根据实际需求确保重要操作更优先
启用延迟插入改善大批量写入性能
尽量顺序操作让insert数据都写入到尾部,减少阻塞
分解大的操作,降低单个操作的阻塞时间
降低并发数,某些高并发场景通过应用来进行排队机制
对于相对静态的数据,充分利用Query Cache可以极大的提高访问效率
MyISAM的Count只有在全表扫描的时候特别高效,带有其他条件的count都需要进行实际的数据访问

InnoDB

特性
具有较好的事务支持:支持4个事务隔离级别,支持多版本读
行级锁定:通过索引实现,全表扫描仍然会是表锁,注意间隙锁的影响
读写阻塞与事务隔离级别相关
具有非常高效的缓存特性:能缓存索引,也能缓存数据
整个表和主键以Cluster方式存储,组成一颗平衡树
所有Secondary Index都会保存主键信息

适用场景
需要事务支持(具有较好的事务特性)
行级锁定对高并发有很好的适应能力,但需要确保查询是通过索引完成
数据更新较为频繁的场景
数据一致性要求较高
硬件设备内存较大,可以利用InnoDB较好的缓存能力来提高内存利用率,尽可能减少磁盘 IO

最佳实践
主键尽可能小,避免给Secondary index带来过大的空间负担
避免全表扫描,因为会使用表锁
尽可能缓存所有的索引和数据,提高响应速度
在大批量小插入的时候,尽量自己控制事务而不要使用autocommit自动提交
合理设置innodb_flush_log_at_trx_commit参数值,不要过度追求安全性
避免主键更新,因为这会带来大量的数据移动

在实际工作中,选择一个合适的存储引擎是一个比较复杂的问题。每种存储引擎都有自己的优缺点,不能笼统地说谁比谁好。
InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。     如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。        如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rolback)。
MyISAM:插入数据快,空间和内存使用比较低。     如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低,也可以使用。
MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。       如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。
注意,同一个数据库也可以使用多种存储引擎的表。如果一个表要求比较高的事务处理,可以选择InnoDB。这个数据库中可以将查询要求比较高的表选择MyISAM存储。如果该数据库需要一个用于查询的临时表,可以选择MEMORY存储引擎。

如何选择:
1.是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;
2.如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读也有写,请使用InnoDB。
3.系统奔溃后,MyISAM恢复起来更困难,能否接受;
4.MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共脂的,如果你不知道用什么,那就用InnoDB,至少不会差。
InnoDB为什么推荐使用自增ID作为主键?
答:自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。   如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。
innodb引擎的4大特性
插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)

3、简述数据三大范式?


什么是范式?
简言之就是,数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。(简单来说,就是根据需要,来优化数据存储方式!)

一般地,在进行数据库设计时,应遵循三大原则,也就是我们通常说的三大范式:

   第一范式要求确保表中每列的原子性,也就是不可拆分;

  第二范式要求确保表中每列与主键相关,而不能只与主键的某部分相关(主要针对联合主键),主键列与非主键列遵循完全函数依赖关系,也就是完全依赖;

  第三范式确保主键列之间没有传递函数依赖关系,也就是消除传递依赖。

4、什么是事务?MySQL如何支持事务?


在mysql中用的最多的存储引擎有:innodb,bdb,myisam ,memory 等。其中innodb和bdb支持事务而myisam等不支持事务。

5、简述数据库设计中一对多和多对多的应用场景?


一对多:当在数据库的设计中,涉及到一个对象可以包含多个另外对象,而单个另外对象只能对应一个对象时就产生了一对多的关系。  例学生和班级,这种情况通常将外键设在多的对象表结构中。
多对多:当在数据库的设计中,涉及到一个对象可以包含多个另外对象,而单个另外对象也对应多个对象时就产生了多对多的关系,  例书籍和作者,这种情况通常将外键设在多的对象表结构中。

6、如何基于数据库实现商城商品计数器?


如果是高并发情况下,建议用内存数据库redis去实现计数的功能。如果不是那么高的并发,用表实现就可以。

7、常见SQL(必备)答案   8、简述触发器、函数、视图、存储过程?


触发器:使用触发器可以定制用户对表进行【增、删、改】操作时前后的行为,触发器无法由用户直接调用,而知由于对表的【增/删/改】操作被动引发的
函数:是MySQL数据库提供的内部函数(当然也可以自定义函数)。这些内部函数可以帮助用户更加方便的处理表中的数据
视图:视图是虚拟表或逻辑表,它被定义为具有连接的SQL SELECT查询语句。
存储过程:存储过程是存储在数据库目录中的一坨的声明性SQL语句,数据库中的一个重要对象,有效提高了程序的性能

9、MySQL索引种类


1.普通索引
2.唯一索引
3.主键索引
4.组合索引
5.全文索引
名词:
    - 覆盖索引:在索引文件中就可以把想要的数据得到,无需再去物理表中查询。        
    - 索引合并:使用多个单列索引去查找数据。 

10、索引在什么情况下遵循最左前缀的规则?


在建立了联合索引的前提下: index1:(a,b,c),只会走a、a,b、a,b,c 三种类型的查询,其实这里说的有一点问题,a,c也走,但是只走a字段索引,不会走c字段。
索引是有序的,index1索引在索引文件中的排列是有序的,首先根据a来排序,然后才是根据b来排序,最后是根据c来排序。

11、主键和外键的区别?


主键:唯一标识一条记录,不能有重复的,不允许为空
外键:表的外键是另一表的主键, 外键可以有重复的, 可以是空值

12、MySQL常见的函数?


1、聚合函数:avg,min,max,count,sum,2、字符串处理函数:
合并字符串函数:concat(str1,str2,str3…)
比较字符串大小函数:strcmp(str1,str2)
获取字符串字节数函数:length(str)
获取字符串字符数函数:char_length(str)
字母大小写转换函数:大写:upper(x),ucase(x);小写lower(x),lcase(x)
3、处理数值的函数:
绝对值函数:abs(x)
向上取整函数:ceil(x)
向下取整函数:floor(x)
取模函数:mod(x,y)
随机数函数:rand()
四舍五入函数:round(x,y)4、用于处理时间日期的函数:
获取当前日期:curdate(),current_date()
获取当前时间:curtime(),current_time()
获取当前日期时间:now()
从日期中选择出月份数:month(date),monthname(date)
从日期中选择出周数:week(date)
从日期中选择出周数:year(date)
从时间中选择出小时数:hour(time)
从时间中选择出分钟数:minute(time)
从时间中选择出今天是周几:weekday(date),dayname(date)

13、列举 创建索引但是无法命中索引的8种情况。


以下id(主键)email,num为索引

1- like '%xx'
    select * from tb1 where email like '%cn';
  数据量比较大的情况下避免使用like
    
2- 使用函数
    select * from tb1 where reverse(email) = 'wupeiqi';  #可以在python代码中先把‘wupeiqi’翻转过来
3- or
    select * from tb1 where id = 1 or email= 'seven@live.com';
    特别的:当or条件中有未建立索引的列才失效,以下会走索引
            select * from tb1 where id = 1 or name = 'seven';
            select * from tb1 where id = 1 or name = 'seven@live.com' and email = 'alex'
4- 类型不一致
    如果列是字符串类型,传入条件是必须用引号引起来,不然...
    select * from tb1 where email = 999;
5- !=
    select * from tb1 where email != 'alex'
    特别的:如果是主键,则还是会走索引
        select * from tb1 where id != 123
6- >
    select * from tb1 where email > 'alex'
    特别的:如果是主键或索引是整数类型,则还是会走索引
        select * from tb1 where id > 123
        select * from tb1 where num > 123
7- order by
    select name from tb1 order by email desc;
    当根据索引排序时候,选择的映射如果不是索引,则不走索引
    特别的:如果对主键排序,则还是走索引:
        select * from tb1 order by id desc;
 
8- 组合索引最左前缀
    如果组合索引为:(id,email)
    id and email       -- 使用索引
    id                 -- 使用索引
    email                -- 不使用索引

14、如何开启慢日志查询?


slow_query_log = ON     # 开启慢日志记录
slow_query_log_file = C:\Software\mysql56\data\Markben-slow.log      #日志文件

long_query_time = 2                   #时间限制,超过此时间,则记录
log_queries_not_using_indexes = OFF    #为使用索引的搜索是否记录 

15、数据库导入导出命令(结构+数据)?


1,导出dbname库所有表结构
mysqldump -uroot -ppasswd -d dbname >db.sql; 

2,导出dbname库test表结构
mysqldump -uroot -ppasswd -d dbname test>db.sql; 

3,导出dbname库结构和数据
mysqldump -uroot -ppasswd  dbname >db.sql; 

4,导出dbname库test表结构和数据
mysqldump -uroot -ppasswd dbname test>db.sql; 

(以上均为操作系统命令,不是mysql命令) 

5,导入sql文件
mysql -u用户名 -p密码 数据库名 < 数据库名.sql

16、数据库优化方案?


1、选取最适用的字段属性 - 创建表时尽量用 char 代替 varchar
2 尽量使用短索引
    create index ixxx on tb1(title(16)) # 用title前16个字符做索引
3、使用连接(JOIN)来代替子查询(Sub-Queries)JOIN是因为MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。
4 组合索引代替多个单列索引(经常使用多个条件查询时)
5、使用外键
6 避免使用select *
7 count(1)count() 代替 count(*)
8 表的字段顺序固定长度的字段优先
9 连表时注意条件类型需一致
10、索引散列值(重复少)不适合建索引,例:性别不适合11、缓存:利用redismemcache,将常用的数据放入缓存中

- 1.SQL语句优化
1)应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
2)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值**,然后这样查询:
select id from t where num=0
3)很多时候用 exists 代替 in 是一个好的选择
4)用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤

- 2.索引优化
合理使用:普通索引、唯一索引(主键索引、唯一索引)、联合索引、全文索引、空间索引

- 3.数据库结构优化
1)范式优化:
比如消除冗余(节省空间。。)
2)反范式优化:
比如适当加冗余等(减少join)
3)拆分表:
分区将数据在物理上分隔开,不同分区的数据可以制定保存在处于不同磁盘上的数据文件里。这样,当对这个表进行查询时,只需要在表分区中进行扫描,而不必进行全表扫描,明显缩短了查询时间,另外处于不同磁盘的分区也将对这个表的数据传输分散在不同的磁盘I/O,一个精心设置的分区可以将数据传输对磁盘I/O竞争均匀地分散开。对数据量大的时时表可采取此方法。可按月自动建表分区。
4)拆分其实又分垂直拆分和水平拆分:
案例: 简单购物系统暂设涉及如下表:
1.产品表(数据量10w,稳定)
2.订单表(数据量200w,且有增长趋势)
3.用户表 (数据量100w,且有增长趋势) 以mysql为例讲述下水平拆分和垂直拆分,mysql能容忍的数量级在百万静态数据可以到千万。
垂直拆分:解决问题:表与表之间的io竞争 。不解决问题:单表中数据量增长出现的压力。
方案: 把产品表和用户表放到一个server上 订单表单独放到一个server上
水平拆分: 解决问题:单表中数据量增长出现的压力 不解决问题:表与表之间的io争夺。
方案: 用户表通过性别拆分为男用户表和女用户表,订单表通过已完成和完成中拆分为已完成订单和未完成订单, 产品表、未完成订单放一个server上;已完成订单表和男用户表放一个server上;女用户表放一个server上(女的爱购物 哈哈)
- 4.服务器硬件优化

17、char和varchar的区别?


char的长度是不可变的,而varchar的长度是可变的。
char的存取速度还是要比varchar要快得多,因为其长度固定,方便程序的存储与查找;
但是char也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间,可谓是以空间换取时间效率,而varchar是以空间效率为首位的。
再者,char的存储方式:对英文字符(ASCII)占用1个字节,对一个汉字占用2个字节;而varchar的存储方式:对每个英文字符占用2个字节,汉字也占用2个字节。

18、简述MySQL的执行计划?


在工作过程中,有时候会对慢查询进行调优。对于MySQL的SQL语句调优,MySQL本身提供了强大的explain关键字用于查询分析执行计划。
语法:explain + SQL语句从语法角度explain和describe/desc是相同的,只是一般更常用desc看表结构,explain来看查询计划。

19、在对name做了唯一索引前提下,简述以下区别:


select * from tb where name = ‘Oldboy-Wupeiqi’ # 全局遍历找所有
select * from tb where name = ‘Oldboy-Wupeiqi’ limit 1 # 锁定一条就结束

20、1000w条数据,使用limit offset 分页时,为什么越往后翻越慢?如何解决?


原因:越是向后,扫描的数据也就越多
解决方案:
1、limit限制优化法:把limit偏移量限制低于某个数。超过这个数等于没数据
2、存储本页数据两端的主键,按主键查找后向前或向后取多少条

21、什么是索引合并?


索引合并:是把几个索引的范围扫描合并成一个索引。
索引合并的时候,会对索引进行并集,交集或者先交集再并集操作,以便合并成一个索引。
这些需要合并的索引只能是一个表的。不能对多表进行索引合并。

22、什么是覆盖索引?


MySQL可以利用索引返回SELECT 列表中的字段。而不必根据索引再次读取数据文件。 
包含所有满足查询需要的数据的索引成为覆盖索引(Covering Index)。也就是平时所说的不需要回表操作

是否这样说容易理解:在索引文件中就可以把想要的数据得到,不必读取数据行
索引覆盖可以大大提高查询速度,在大数据量的时候尤其明显

23、简述数据库读写分离?


读写分离为了确保数据库产品的稳数据定性,很多数据库拥有双机热备功能。
也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进行读的操作。

24、简述数据库分库分表?(水平、垂直)


垂直分库:就是按照功能的不同,把没有关联的数据放到不同的数据库和服务器中
水平分表:根据一定的规则将一个表的数据划分到不同的数据库中,两个数据库的表结构一样。

25、left join、right join以及inner join的区别


left join 左关联,主表在左边,右边为从表。如果左侧的主表中没有关联字段,会用null 填满
right join 右关联 主表在右边和letf join相反
inner join 内关联只会显示主表和从表相关联的字段,不会出现null

26、写出一条Sql语句:取出表A中第31到第40记录 (Mysql)


select * from A limit 30, 10

27、从数据库中随机取50条数据


select * from 表 order by rand() limit50;

28、什么是sql注入


SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,
通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

29、关于sql语句应该考虑哪些安全性?


1.防止sql注入,对特殊字符进行转义,过滤或者使用预编译的sql语句绑定变量。
2.最小权限原则,特别是不要用root账户,为不同的类型的动作或者组建使用不同的账户。
3.当sql运行出错时,不要把数据库返回的错误信息全部显示给用户,以防止泄漏服务器和数据库相关信息。

30、什么是数据库约束,常见的约束有哪几种?


数据库约束用于保证数据库、表数据的完整性(正确性和一致性)。可以通过定义约束\索引\触发器来保证数据的完整性。
总体来讲,约束可以分为:
主键约束:primary key;
外键约束:foreign key;
唯一约束:unique;
检查约束:check;
空值约束:not null;
默认值约束:default;

31、redis和memcached比较?


1.存储容量:
memcached超过内存比例会抹掉前面的数据,而redis会存储在磁盘
2.支持数据类型:
memcached只支持string;
redis支持更多;如:hash、list、集合、有序集合
3.持久化:
redis支持数据持久化,可以将内存中的数据保持在磁盘中,memcached无
4.主从:
Redis支持数据的备份,即master-slave模式的数据备份;
5.特性 Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,Memcached只是简单的K/V缓存

1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;
2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;
3、虚拟内存--Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;
4、过期策略--memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10;
5、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;
6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);
7、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;
8、Redis支持数据的备份,即master-slave模式的数据备份;

在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别(我个人是这么认为的)。
Redis 只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,
Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,
同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据 是不会进行
swap操作的。

同时由于Redis将内存中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,
Redis将阻塞这个操作,直到子线程完成swap操作后才可以进行修改。

32、redis中数据库默认是多少个db 及作用?


#redis默认有16个db,db0~db15(可以通过配置文件支持更多,无上限)
#并且每个数据库的数据是隔离的不能共享
#可以随时使用SELECT命令更换数据库:redis> SELECT 1
# 注意:
      多个数据库之间并不是完全隔离的
      比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据。

33、python操作redis的模块?


import redis
# 基本操作
r = redis.Redis(host='127.0.0.1',port=6379)
r.set('name','xiaoming')

# 连接池
pool = redis.ConnectionPool(host='127.0.0.1',port=6379)
r = redis.Redis(connection_pool=pool)
r.set('name','xiaoming')

34、如果redis中的某个列表中的数据量非常大,如果实现循环显示每一个值?


# 通过scan_iter分片取,减少内存压力
scan_iter(match=None, count=None)增量式迭代获取redis里匹配的的值
# match,匹配指定key
# count,每次分片最少获取个数
    r = redis.Redis(connection_pool=pool)
    for key in r.scan_iter(match='PREFIX_*', count=100000):
        print(key)

35、redis如何实现主从复制?以及数据同步机制?


实现主从复制:
'创建6379和6380配置文件'
redis.conf:6379为默认配置文件,作为Master服务配置;
redis_6380.conf:6380为同步配置,作为Slave服务配置;
'配置slaveof同步指令'
在Slave对应的conf配置文件中,添加以下内容:
slaveof 127.0.0.1 6379
数据同步步骤:
(1)Slave服务器连接到Master服务器.
(2)Slave服务器发送同步(SYCN)命令.
(3)Master服务器备份数据库到文件.
(4)Master服务器把备份文件传输给Slave服务器.
(5)Slave服务器把备份文件数据导入到数据库中.

36、redis中的sentinel的作用?


1):Master状态检测
2):如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Master作为Slave
3):Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换

37、如何实现redis集群?


基于【分片】来完成。

- 集群是将你的数据拆分到多个Redis实例的过程
- 可以使用很多电脑的内存总和来支持更大的数据库。
- 没有分片,你就被局限于单机能支持的内存容量。
redis将所有能放置数据的地方创建了 16384 个哈希槽。
如果设置集群的话,就可以为每个实例分配哈希槽:
- 192.168.1.20【0-5000】
- 192.168.1.21【5001-10000】
- 192.168.1.22【10001-16384】

以后想要在redis中写值时:set k1 123
- 将k1通过crc16的算法转换成一个数字,然后再将该数字和16384求余,
- 如果得到的余数 3000,那么就将该值写入到 192.168.1.20 实例中。

集群方案:
- redis cluster:官方提供的集群方案。
- codis:豌豆荚技术团队。
- tweproxy:Twiter技术团队。

38、redis中默认有多少个哈希槽? –16384

39、简述redis的有哪几种持久化策略及比较?


Redis 提供了多种不同级别的持久化方式:
RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。

Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。

你甚至可以关闭持久化功能,让数据只在服务器运行时存在。

40、列举redis支持的过期策略。


redis 过期策略是:定期删除+惰性删除。
所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

41、MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如何保证 redis 中都是热点数据?


限定Redis占用的内存,根据自身数据淘汰策略,淘汰冷数据,把热数据加载到内存。计算一下 20W 数据大约占用的内存,然后设置一下Redis内存限制即可。

42、写代码,基于redis的列表实现 先进先出、后进先出队列、优先级队列。


先进lpush keys values 先出 rpop keys
先进lpush keys values 后出 lpop keys

43、如何基于redis实现消息队列?


Redis中五大数据结构之一—列表,其PUSH和POP命令遵循FIFO先进先出原则。当我们需要发布消息的时候执行LPUSH(消息从左边进入队列),
消息接收端执行RPOP获得消息(消息从右侧弹出)。对于列表,Redis提供了带有阻塞的命令(命令前加B)。因此,生产者lpush消息,
消费者brpop(从列表中弹出最右端元素,如无元素则一直阻塞到timeout)消息,并设定超时时间timeout,可以减少redis的压力。

44、如何基于redis实现发布和订阅?以及发布订阅和消息队列的区别?


创建一个频道 客户端加入频道 等待频道发布订阅

45、什么是codis及作用?


Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说,连接到 Codis-Proxy(redis代理服务)和连接原生的 Redis-Server 没有明显的区别, 
上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 
所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务.

46、什么是twemproxy及作用?


Twemproxy是Twtter开源的一个 Redis 和 Memcache 代理服务器,主要用于管理 Redis 和 Memcached 集群,减少与Cache服务器直接连接的数量。
它的后端是多台redis或memcached,所以也可以被称为分布式中间件。
作用:
通过代理的方式减少缓存服务器的连接数。
自动在多台缓存服务器间共享数据。
通过配置的方式禁用失败的结点。
运行在多个实例上,客户端可以连接到首个可用的代理服务器。
支持请求的流式与批处理,因而能够降低来回的消耗。

47、写代码实现redis事务操作。


import redis
pool = redis.ConnectionPool(host='10.211.55.4', port=6379)
conn = redis.Redis(connection_pool=pool)
# pipe = r.pipeline(transaction=False)
pipe = conn.pipeline(transaction=True)
# 开始事务
pipe.multi()
pipe.set('name', 'zgc')
pipe.set('role', 'haha')
pipe.lpush('roless', 'haha')
# 提交
pipe.execute()
'注意'咨询是否当前分布式redis是否支持事务

48、redis中的watch的命令的作用?


Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断

49、基于redis如何实现商城商品数量计数器?


实现商城秒杀并发思路而已
1:秒杀活动开始之前,将商品的SKU和库存存入redis中
redis Template.expire(商品的SKU,25,TimeUnit.HOURS);#以商品的唯一标识做为key,缓存24小时
2:商品下单方法中增加一个计数器,以商品SKU为KEY,计数器为原子性,不存在并发问题long count=redisTemplate.opsForValue0.increment(商品SUK,1);
3:提交订单时,从redis中获取商品SKU的库存量,和计数器中的count比较,如果大于等于count,说明秒杀完了
4:同步库存量到数据库

50、简述redis分布式锁和redlock的实现机制。


在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段。
    一个Client想要获得一个锁需要以下几个操作:
    得到本地时间Client使用相同的key和随机数,按照顺序在每个Master实例中尝试获得锁。在获得锁的过程中,为每一个锁操作设置一个快速失败时间(如果想要获得一个10秒的锁, 那么每一个锁操作的失败时间设为5-50ms)。
    这样可以避免客户端与一个已经故障的Master通信占用太长时间,通过快速失败的方式尽快的与集群中的其他节点完成锁操作。
    客户端计算出与master获得锁操作过程中消耗的时间,当且仅当Client获得锁消耗的时间小于锁的存活时间,并且在一半以上的master节点中获得锁。才认为client成功的获得了锁。
    如果已经获得了锁,Client执行任务的时间窗口是锁的存活时间减去获得锁消耗的时间。
    如果Client获得锁的数量不足一半以上,或获得锁的时间超时,那么认为获得锁失败。客户端需要尝试在所有的master节点中释放锁, 即使在第二步中没有成功获得该Master节点中的锁,仍要进行释放操作。

51、Redis分布式锁如何续期?


采用redisson这个客户端工具:
如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了1easeTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

52、什么是一致性哈希?Python中是否有相应模块?


一致性哈希
一致性hash算法(DHT)可以通过减少影响范围的方式,解决增减服务器导致的数据散列问题,从而解决了分布式环境下负载均衡问题;
如果存在热点数据,可以通过增添节点的方式,对热点区间进行划分,将压力分配至其他服务器,重新达到负载均衡的状态。
模块:hash_ring

53、如何高效的找到redis中所有以oldboy开头的key?


key oldboy*

随机文章