该篇文章从关系型数据库和非关系型数据库来讲述,牵扯到设计、索引、隔离级别以及redis的应用场景、持久化、等进行详细描述,希望对您有用!
1、你是怎么设计数据库的?
设计数据库首先要遵循三大范式要求:原子性、依赖性、关联性
1.原子性是指数据库表的每一列都是不可分割的原子数据项
2.依赖性是指实体的属性完全依赖于主关键字。
3.关联性是指任何非主属性不依赖于其它非主属性
对于数据库设计来说,不仅仅要考虑范式要求,为了节省查询效率,允许适当的有一些冗余字段。
关系型数据库
关系型数据是面向对象的设计,每一张表都是用来描述一类事物的,每一列都是用
来描述事物的属性的,每一行都是一条记录、一个对象。以下是常用的:
mysql mysql属于oracle旗下的免费的轻量级的 (使用面广,互联网公司)
oracle 收费的重量级的数据库(常用于银行、保险、石油这些项目)
sqlServer (windows平台的开发 、net的语言)
DB2 类似于oracle(银行项目)
1.1数据库索引是什么?
索引是数据库提供的利于快速查询的机制,索引类似于书签目录,
当查询条件那一列做了索引之后,那么数据库会去硬盘索引文件
当中找到满足条件记录的物理位置,直接就可以定位以及获取记录.
1.2索引的种类有哪些?
1:主键索引
2:唯一索引
3:单列索引
4:外键索引
前面四种命中规则,查询条件当中包含该列 列名=列值
5:组合索引 命中规则是最左原则 比如对 a b c 三列创建组合索引,
一旦使用到a这一列就会命中组合索引
select * from items where a=? and b=? 命中索引
select * from items where a=? 命中索引
select * from items where b=? and c=? 没有命中
1.3 sql怎么调优,索引命中怎么知晓?(重点)
使用explain关键字查看sql的执行计划,可以看到该sql的
索引命中情况、索引命中类型、命中率等相关的信息,通过这种方式
可以对sql语句进行调优,对关键查询的条件创建索引以及注意一下sql语句的
用法
尽量不使用like,尽量避免在某一列上进行运算,
不使用 in not in 使用exist not exist等等代替
1.4索引的常用数据结构?
hash索引 hash 均匀分布
B树索引 B树 分布有序
比如我对A列分别建立Hash索引和B树索引,当我频繁对A列的数据进行修改的时候,
性能高,但是如果按照范围进行查找的话,B树索引的性能高(where A>100 and A<1000)
1.5索引有什么优缺点?
索引可以提高查询的效率,但是对记录进行增删改的时候,由于数据库需要去维护
索引文件,所以说如果频繁修改记录的话,影响数据库性能。我们在项目当中创建
索引的时候,只是针对于那些频繁查询的字段创建索引,通常情况下创建索引的列
不会超过6个
1.6 sql语句(笔试题甚至面试时)
group by 分组 子查询 内连接 常用函数 count
1.7你用过存储过程么?
存储过程是预编译的,类似于函数,存储过程可以写sql语句加流程语句
create Producer A(输入参数,输出参数)
begin
//可以写sql while if语句
end
call A();
当时我们数据库当中做了一个批量更新,使用到了存储过程
存储过程的优点,一次编写,多次调用;缺点在分布式环境下,移植性有问题
单库使用存储过程比较多.
1.8 mysql的存储引擎有哪些,有什么区别
常用的就是InnoDB 数据库默认引擎是InnoDB ,它对大规模写入的支持较好,支持数据库事务,支持外键,
主要用于主从机构当中的主服务器 MYISAM 它对大规模读的支持比较好,主要用于从服务器
1.9数据库的事务隔离级别
有4种:
读 未提交
读 已提交
可重复性读
串行化
mysql默认隔离级别 可重复性读
1.10 Oracle的主键自增以及分页
通过序列 sequence 来实现自增
oracle不支持limit语句的,需要通过伪列rownum 进行两次子查询来实现分页
非关系型数据库
0.什么是NoSQL
NoSQL,泛指非关系型数据库,NoSQL即Not-Only_SQL,它可以作为关系型数据库的良好补充。NoSQL数据库的产生就是为了解决大规模数据库集合
多重数据库种类带来的挑战,尤其是大数据应用的难题。Nosql说白了就是不能使用sql了,不是关系型数据库,解决高并发的问题。
因为像mysql或oracle单机能够承受的并发数最多也就几千
1 Redis
Redis是用C语言开发的一个开源的高性能键值对数据库。它通过提供多种键值数据类型来适用不同场景下的
存储需求,目前为止redis支持的键值数据类型有五种:
1.字符串类型 string: redis中没有使用C语言的字符串表示,而是自定义一个数据结构叫SDS(simple dynamic string)即简单动态字符串。
2.散列类型 hash:hash叫散列类型,它提供了字段和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其它类型
3.列表类型 list
4.集合类型 set
5.有序集合类型
redis的字符串是二进制安全的,
0.1什么是二进制安全?
简单理解就是存入什么数据取出的还是什么数据
0.2 redis hash(散列类型)存储比关系数据库的好处?
两者都可以存放对象,对于关系型数据来说,存储数据比较严格、有事务控制,安全性更高,
但是关系型数据库在并发压力下性能很低,所以使用redis hash类型可以在一定程序上
替代关系型数据库,因为redis单机并发量支持10万+
0.3 redis sorted set介绍
在集合类型的基础上有序集合类型为集合中的每个元素都关联一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在在集合中,
还能够获得分数最高或最低的前N个元素、获取指定分数范围内的元素等与分数有关的操作。
在某些方面有序集合和列表类型有些相似。
1、二者都是有序的。
2、二者都可以获得某一范围的元素。
但是,二者有着很大区别:
1、列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会变慢。
2、有序集合类型使用散列表实现,所有即使读取位于中间部分的数据也很快。
3、列表中不能简单的调整某个元素的位置,但是有序集合可以(通过更改分数实现)
4、有序集合要比列表类型更耗内存。
1.1 redis的哨兵机制
redis主从之间可以通过哨兵进行检查,如果主节点出现故障,会自动切换从节点为主
1.2 redis cluster集群原理
redis cluster集群默认16384个hash槽,集群搭建成功之后,需要给每一个主节点
分配hash槽。当外部数据插入的时候,会对key进行crc16然后对16384取模,这样
就计算出哪个节点对该数据进行管理。我们在项目当中采用的3主3从的结构,主从之间通过哨兵,出现故障自动切换.
1.3 你们在项目当中哪些地方用到redis?
1:我们项目当中一些字典表数据,通过redis进行缓存提高查询性能,比如品牌表省市县表等等
2:我们利用redis的过期策略,短信验证码存入redis,两分钟之内有效
3:我们整个项目架构采用redis充当session容器,实现分布式环境下的session共享
4:我们利用redis的list队列,基于push pop的原子性,实现商品抢购秒杀的场景
1.4 缓存的穿透和雪崩问题,你们是如何解决的?
穿透 顾名思义,就是大量的请求穿过缓存层,达到数据库,造成数据库压力过大
举例:你登录淘宝之后,订单搜索,你输入一个无效的订单,通过压测工具恶意攻击
解决方案:1.每次请求时,可以在redis层,做一个bitMap,先去bitmap中查询一下是否存在该条件,进行过滤
2.每次请求,查询数据库就算不存在,我也将查询条件和null在redi中进行缓存
雪崩是指在某一个时间点,大量的缓存同时失效,请求达到数据库,造成数据库压力过大
解决方案:对大量数据设置过期时间时,哪怕业务需要同时失效,我也不设置同一个时间,分别对每一组key value
设置失效时间,让每一组key value的失效时间间隔个几毫秒
1.5 redis是单线程执行的,为什么性能这么高?
redis通过C语言实现了多路复用 轮询的机制,保证了高性能(NIO)
1.6 Redis的应用场景
内容缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用)
分布式集群架构中的session分离。
聊天室的在线好友列表。
任务队列。(秒杀、抢购、12306等等)100件iphonex免费赠送,
应用排行榜。
网站访问统计。
数据过期处理(可以精确到毫秒)
1.7持久化
Redis的高性能是由于其将所有数据都存储在了内存中,为了使Redis在重启之后仍能保证数据不丢失,
需要将数据从内存中同步到硬盘中,这一过程就是持久化。
Redis支持两种方式的持久化,一种是RDB方式,一种是AOF方式。可以单独使用其中一种或将二者结合使用。
1.7.1 RDB持久化
RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘。
RDB是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:
save 900 1
save 开头的一行就是持久化配置,可以配置多个条件(每行配置一个条件),每个条件之间是“或”的关系
1.7.2 AOF持久化
默认情况下Redis没有开启AOF(append only file)方式的持久化,可以通过appendonly参数开启:appendonly yes
开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬
盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof,
可以通过appendfilename参数修改:appendfilename appendonly.aof.
1.7.3 问题总结:
通过RDB方式实现持久化,一旦Redis异常退出,就会丢失最后一次快照以后更改的所有数据。
这就需要开发者根据具体的应用场合,
通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受的范围。如果数据很重要以至于
无法承受任何损失,则可以考虑使用AOF方式进行持久化。
项目当中必须使用rdb,手动开启aof,来保证数据的完整性
1.8 Redis的停止:
强行终止redis进程可能会导致redis持久化数据丢失
正确的方法应该是向redis发送shutdown命令
1.9 Redis实例
一个redis进程就是一个redis实例,一台服务器可以同时有多个redis实例,不同的redis实例提供不同的服务端口对外提供服务,
每个redis实例之间互相影响。每个redis实例都包括自己的数据库,数据库中可以存储自己的数据。
2.0多数据库测试
一个Redis实例可以包括多个数据库,客户端可以指定连接某个redis实例的哪个数据库,就好比一个mysql中创建多个数据库,客户端连接时指定连接哪个数据库。
一个redis实例最多可提供16个数据库,下标从0到15,客户端默认连接第0号数据库,也可以通过select选择连接哪个数据库