Mysql/Redis数据库基础知识的整理

Mysql/Redis基础知识的整理

Celery的底层原理

celery是基于python实现的一个异步任务的调度工具,同时还是一个任务队列,主要用于处理耗时的任务:

celery主要由三部分组成:

  1. 消息中间件(message broker)
    消息中间键,是任务调度队列,是一个独立服务,是一个生产者与消费者模式,生产者把任务放进队列中,消费者(worker)从任务队列中取出任务执行,任务的执行可以按照顺序依次执行;也可以按照计划时间进行,但是(broker)本身不提供队列的服务,所以要集成第三方队列,推荐使用Redis。
  2. 任务的执行单元(worker)
    任务执行单元(worker):即执行任务的程序可以有多个并发。它实时监控消息队列,获取队列当中调度的任务,并执行它。
  3. 任务执行结果的存储(task result store )
    由于任务执行同主程序分开,如果主程序想要获取任务的执行结果必须通过中间件存储,同消息中间件一样,存储也可以使用Redis,假如不需要执行的结果也可以不需要这个配置。

使用场景:

一般使用在比较耗时的场景中;比如:发送短信和邮箱的验证还有我们django中详情页面的静态化

MySQL如何实现快速查找

物理硬件方面:要公司前期投入

SQL优化

1.  对经常使用的字段建立索引
2.  对于查询的数据建立缓存, 例如把省市区的信息缓存,
3.  对于等价的谓词: 把原来的between and  更改为 <= 
4.  在where语句里面,尽量少使用外连接,尽可能使用内链接。


SQL优化一般理解是让SQL运行更快。实现MySQL优化可以从下面这些角度实现:
1. 在查询频率高的字段建立索引和缓存,对于经常查询的数据建立索引会提升查询速度,同时把经常用的数据进行缓存,避免对数据库的多次查询减少磁盘的IO,节约时间。

2. 在where查询子语句上尽量避免对字段的NULL值判断,否则数据库引擎将会放弃索引而使用全表扫描. 如:	select id from t where num is null	可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0
    
3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。	
    
4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:	
select id from t where num=10 or num=20	
可以这样查询:	
select id from t where num=10	
union all	
select id from t where num=20	
    
5.in 和 not in 也要慎用,否则会导致全表扫描,如:	
select id from t where num in(1,2,3)	
对于连续的数值,能用 between 就不要用 in 了:	
select id from t where num between 1 and 3	
    
6.下面的查询也将导致全表扫描:	
select id from t where name like '%abc%'	
    
7.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:	
select id from t where num/2=100	
应改为:	
select id from t where num=100*2	
    
8.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:	
select id from t where substring(name,1,3)='abc'--name以abc开头的id	
应改为:	
select id from t where name like 'abc%'	
    
9.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。	
    
10.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,	
否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。	
    
11.不要写一些没有意义的查询,如需要生成一个空表结构:	
select col1,col2 into #t from t where 1=0	
这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:	
create table #t(...)	
    
12.很多时候用 exists 代替 in 是一个好的选择:	
select num from a where num in(select num from b)	
用下面的语句替换:	
select num from a where exists(select 1 from b where num=a.num)	
    
13.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,	
如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。	
    
14.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。	
    
15.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。	
这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。	
    
16.尽可能的使用 varchar 代替 char ,因为首先变长字段存储空间小,可以节省存储空间,	其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。	
17.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。	
    
18.避免频繁创建和删除临时表,以减少系统表资源的消耗。

19.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。	
    
20.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,	
以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。

21.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。	
    
22.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。	
    
23.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。

24.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。
在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。
25.尽量避免大事务操作,提高系统并发能力。26.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。 

其他的SQL优化参考:
1. https://blog.csdn.net/z719725611/article/details/52922695
2. https://blog.csdn.net/heqinghua217/article/details/78600967
3. https://blog.csdn.net/wwzuizz/article/details/54602058
4. https://www.cnblogs.com/easypass/archive/2010/12/08/1900127.html

Redis如何做持久化

持久化: 把数据存放到断电也不会丢失的设备中,例如: 文件, mysql

如何实现持久化
  1. 快照(RDB),是redis默认做持久化的方式

    实现原理:

    ​ redis是由C语言实现的,fork函数,会把主进程复制一个子进程, 子进程会把内存的数据依次遍历出来,存放到配置指定的二进制文件dump.rdb中。

实现快照:

​ 只要更改配置文件,默认提供额三种级别的快照形式

1538014151203

优点:

  1. 使用起来简单,只要修改配置文件,把所有的数据存放到一个文件中,
  2. 文件以二进制形式存放,读写很快

缺点:

​ 断电容易造成数据丢失,断电的时间段内的数据不能备份

  1. AOF(Append only file) , 以日志文件追加的方式实现的

    实现原理:

    把所有内存中数据以writer追加的方法写道日志文件中。
    

    实现:

    修改配置文件,
    

    1538015831088

    优点:

    1. 使用起来简单,只要修改配置文件, 日志文件是单独文件
    2. 可以修改日志文件得大小:BGREWRITERAOF

    缺点:

    1. 大小的限制,

RDB快照
redis是默认做数据持久化的,默认的方式是快照(snapshotting),把内存的数据写入本地的二进制文件dump.rdb文件中。

快照持久化实现原理:
Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件,使用redis的save命令调用这个过程。

快照的配置有下面三个级别,配置是在redis的配置文件中。

RDB快照持久化的优点:

  1. RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如您可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题您也可以根据需求恢复到不同版本的数据集.
  2. RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
  3. RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能。
  4. 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.

RDB快照持久化的缺点:
一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。
AOF
AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件.
实现原理:
在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中,当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容.Redis还能对AOF文件通过BGREWRITEAOF 重写,使得AOF文件的体积不至于过大.

由于AOF是把操作日志写入日志文件中,那么AOF的操作安全性如何保证?可以在配置文件中通过配置告诉redis我们想要使用fsync函数强制写入到磁盘的时间。
配置分为三种:

  1. appendfsync no
    当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。
  2. appendfsync everysec
    当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以,结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。
  3. appednfsync always
    当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。

AOF的优点:

  1. 使用AOF会更加持久化数据。
  2. redis可以在aof文件过大时使用BGREWRITEAOF 进行重写
  3. 保存的aof日志格式文件是按照redis协议的格式保存,很容易读取。
    AOF的缺点:
  4. 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积
  5. 速度没有RDB速度快。
  6. 在写入内存数据的同时将操作命令保存到日志文件,在一个并发更改上万的系统中,命令日志是一个非常庞大的数据,管理维护成本非常高,恢复重建时间会非常长,这样导致失去aof高可用性本意。另外更重要的是Redis是一个内存数据结构模型,所有的优势都是建立在对内存复杂数据结构高效的原子操作上,这样就看出aof是一个非常不协调的部分。其实aof目的主要是数据可靠性及高可用性.

Redis为什么比MySQL快?

  1. redis存储在内存中, mysql 存储在磁盘中。

  2. redis存储的是key/value的键值对,查找的时间复杂度0(1), 常数级别

mysql 存储数据依靠数据引擎: Innodb, MyisAm. l两种引擎都是使用的B-TREE来进行数据的存放或查找

时间复杂度0(logn),对数级别。

  1. mysql存储的时候,一般存放到表格中,开表格查询,通过外键或者内链接外连接;进行磁盘的读写,

    redis查找数据,只要知道key,就可以直接拿到对应的值

  2. redis,是单线程进行多路io服用, 单线程就可以比卖你多线程的创建的时间开销; 多路io复用可以共享数据;

    对于多核的电脑操作redis,把数据进行分区。

Redis有哪些特点?如何向Redis中存储数据?如何设置长连接?

特点:

  1. 快: C语言实现的,把数据都存储在内存中,在内存中存储时是以key/value

  2. 数据类型多:string, List, Set, Zset, Hash

  3. 数据的持久化:

    持久化: 把存储在内存中的数据,写入本地的文件中

    在redis中默认使用快照(RDB)模式进行数据持久化, 以二进制形式写入本地的dump.rdb

  4. 做主从复制: 在主服务器上只进行写的操作,而在从的服务器上进行读的操作

  5. 分布式及高可用

    高可用: 使用Redis自带的哨兵机制

  6. 能支持事务,发布/订阅模式

存储数据

import redis
conn = redis.StricRedis('127.0.0.1', 6379)
conn.lset('key', 'name')
conn.lrange('key', 0 , -1)

设置长连接

修改配置文件redis.conf

tcp-keepalive = 0 # 默认禁用长连接
tcp-keepalive = 1 # 启动长连接  

长连接的概念:

​ 在一个tcp连接时,连接后发送数据,数据发送完成后并不会断开连接,客户端和服务端会发送测试数据来保持连接

短链接概念:在一个tcp连接中,数据发送完成就断开连接, 如果再有数据要发送,就重新建立连接。

长连接的好处: 节约时间

猜你喜欢

转载自blog.csdn.net/weixin_44090435/article/details/87615966