1.1000w条数据,使用limitoffset 分页时,为什么越往后翻越慢,如何解决
增加order by,并且order by字段需要建立索引
2.什么是覆盖索引
sql只需要通过索引就可以返回查询所需要的数据,而不必通过二级索引查到主键之后再去查询数据
3.简述数据库读写分离
主数据库处理事务性查询,从数据库处理select查询
4.简述数据库分库分表
水平分库
以字段为依据,按照一定策略,将一个库中的数据拆分到多个库中,每个库的结构都一样,数据都不一样
水平分表
以字段为依据,按照一定策略,将一个表中的数据拆分到多个表中,每个表的结构都一样,数据都不一样
垂直分库
以表为依据,按照业务归属不同,将不同的表拆分到不同的库中
垂直分表
以字段为依据,按照字段的活跃性,将表中字段拆到不同的表中
5.redis和memcached比较
性能
redis只使用单核,Memcached可以使用多核
100k以下,redis性能更优,反之不行
内存使用效率
使用简单的key-value存储的话,memcached的内存利用率更高
redis采用hash结构来做key-value存储,由于其组合式压缩,会效率高一些
6.redis中数据库默认是多少个db及作用
/etc/redis/redis.conf
databases = 16,默认16
7.python操作redis的模块
import redis red = redis.Redis(host='localhost',port=6379,db=1) string类型存取 set 在redis中设置值,默认不存在则创建,存在则修改 red.set('key','value') mset 批量设置值 get 获取某个key的值 mget 批量获取 strlen 返回key对应值得字节长度 append 在name对应的值后面追加内容 hash类型:一个name对应一个dict字典来存储 hset name对应的hash中设置一个键值对(不存在,则创建,存在则修改) hget 在name对应的hash中根据key获取value hgetall 获取name所有键值对 hmset 在name对应的hash中批量设置键值对,mapping:字典 hmget 在name对应的hash中批量获取键所对应的值 hlen 获取hash键值对的个数 hkeys 获取hash中所有key hvals 获取hash中所value hexists 检查name对应的hash是否存在当前传入的key hdel 删除指定name对应的key所在的键值对,删除成功返回1,失败返回0 hincrby 与hash中key对应的值相加,不存在则创建key=amount(amount为整数) list类型:一个name对应一个列表存储 lpush 元素从list的左边添加,可以添加多个 rpush 元素从list的左边添加,可以添加多个 lpushx 当name存在时,元素才能从list的左边加入 rpushx 当name存在时,元素才能从list的右边加入 llen name列表长度 linsert 在name对应的列表的某一个值前或后插入一个新值 lset 对list中某一个索引位置重新赋值 lrem 删除name对应的list中指定值 lpop 移除列表的左侧第一个元素,返回值则是第一个元素 lindex 根据索引获取列表内元素 lrange 分片获取元素 ltrim 移除列表内没有在该索引之内的值 set类型:集合是不允许重复的列表 sadd 给name对应的集合中添加元素 scard 获取name对应的集合中的元素个数 smembers 获取name对应的集合的所有成员 sdiff 在第一个name对应的集合中且不在其他name对应的集合的元素集合 sismember 检查value是否是name对应的集合内的元素 smove 将某个元素从一个集合中移动到另外一个集合 spop 从集合的右侧移除一个元素,并将其返回 其他常用操作 flushdb 清空当前db中的数据,默认是同步,若开启异步asynchronous=True,会新起一个线程进行清空操作,不阻塞主线程 flushall 清空所有db中的数据,默认是同步,异步同flushdb delete 根据name删除redis中的任意数据类型 keys 根据*?等通配符匹配获取redis的name exists 检查redis的name是否存在 expire 为某个name的设置过期时间 rename 重命名 move 将redis的某个name移动到指定的db下 randomkey 随机获取一个redis的name(不删除) type 获取name对应值的类型
8.如果redis中的某个列表中的数据量非常大,如何实现循环显示每一个值
通过scan_iter分片取,减少内存压力
9.redis如何实现主从复制,以及数据同步机制
主从复制
master以写为主,slavel以读为主
读写分离,容灾恢复
一主二仆:一个master,两个slave,slave只能读不能写
薪火相传:上一个slave可以是下一个slave的master
反客为主:当master挂掉后,slave可键入命令slaveof no one使当前redis停止与其他master redis数据同步,转成master redis
10.redis中的sentinel的作用
redis-sentinel是redis官方推荐的高可用性(HA)解决方案,当用redis做master-slave的高可用方案时,假如master宕机了,redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换
11.如何实现redis集群
官方redis cluster
通过proxy分片
客户端分片
12.redis中默认有多少个哈希槽
16384
13.简述redis有哪几种持久化策略及比较
RDB持久化
RDB非常适用于灾难恢复
RDB可以最大化Redis的性能
RDB在恢复大数据集时的速度比AOF的恢复速度要快
RDB在服务器故障时会丢失数据
AOF持久化
AOF文件是一个只进行追加操作的日志文件
14.列举redis支持的过期策略
volatile-lru:只对设置了过期时间的key进行LRU(默认值)
allkeys-lru : 删除lru算法的key
volatile-random:随机删除即将过期key
allkeys-random:随机删除
volatile-ttl : 删除即将过期的
noeviction : 永不过期,返回错误
15.mysql里有2000w数据,redis中只存20w的数据,如何保证redis中都是热点数据
这里考察的是redis的淘汰机制
noeviction: 不删除策略。当达到最大内存限制时, 如果需要使用更多内存,则直接返回错误信息。(redis默认淘汰策略)
allkeys-lru: 在所有key中优先删除最近最少使用(less recently used ,LRU) 的 key。
allkeys-random: 在所有key中随机删除一部分 key
volatile-lru: 在设置了超时时间(expire)的key中优先删除最近最少使用(less recently used ,LRU) 的 key。
volatile-random:在设置了超时时间(expire)的key中随机删除一部分 key。
volatile-ttl: 在设置了超时时间(expire)的key中优先删除剩余时间(time to live,TTL) 短的key。
16.如何基于redis实现消息队列
redis的list可以用来实现消息队列,key用来表示队列名称,客户端向对应的key代表的队列发消息
发消息采用rpush,lpush实现
取消消息采用rpop,lpop实现
17.如何基于redis实现发布和订阅,以及发布订阅和消息队列的区别
发布订阅是一种消息范式,消息的发送者将消息分类,消息的订阅者接收自己感兴趣的消息
消息队列用来在传输过程中保存消息
18.什么是codis及作用
一个分布式redis解决方案
优点
对客户的透明,与codis交互方式和redis本身交互一样
支持在线数据迁移,迁移过程对客户端透明有简单的管理和监控界面
支持高可用,无论是redis数据存储还是代理节点
自动进行数据的均衡分配
最大支持1024个redis实例,存储容量海量
高性能
缺点
采用自有的redis分支,不能与原版的redis保持同步
如果codis的proxy只有一个,redis的性能会下降20%左右
某些命令不支持,比如事务命令muti
国内开源产品,活跃度相对弱一些
19.什么是twemproxy及作用
twemproxy是一个代理服务器,可以通过它减少redis服务器打开的连接数
用途:
通过代理的方式减少缓存服务器的连接数
自动在多台缓存服务器间共享数据
通过不同的策略与散列函数支持一致性散列
通过配置的方式禁用失败的节点
运行在多个实例上,客户端可以连接到首个可用的代理服务器
支持请求的流式与批处理,因而能够降低来回的消耗
20.写代码实现redis事务操作
事务开始
命令入队
事务执行
21.redis中的watch的命令的作用
watch用于在进行事务操作的最后一步也就是在执行exec之前对某个key进行监视
如果这个被监视的key被改动,那么事务就被取消,否则事务正常执行
22.基于redis如何实现商城数量计数器
redis的incr自增命令就可以实现,每次调用接口之前,先获得下计数器自增后的值,如果小于限制,放行,大于限制,拦截
23.简述redis分布式锁和redlock的实现机制
存在N个Redis服务(奇数个),之间完全独立没有构成集群。
当某个进程获取锁时,如果在N/2+1个Redis服务上成功写入了锁。则获取锁成功。如果获取锁失败,一定要再写入成功了的Redis服务上del
当释放锁时,再N个Redis服务上依次del
当一个客户端获取锁失败时,这个客户端应该在一个随机延时后进行重试,之所以采用随机延时是为了避免不同客户端同时重试导致谁都无法拿到锁的情况出现。
对该算法市面上也有开源项目来实现,如redisson
24.如何高效的找到redis中所有以oldboy开头的key
# 命令模式
KEYS * # *代表通配符
# redis模块
import redis
con = redis.Redis()
con.keys(pattern='celery*') # *代表通配符