1.redis常见的数据结构

redis是一种以键值对存储的高性能内存数据库,有五种常用的数据类型,string,list,hash,set,zset。

2.redis的过期时间

  redis中的key可以设置过期时间,方式有两种,第一种是通过expire命令来设置,expire key seconds。第二种方式是使用setex(string key,int seconds,string value)。

3.过期键的删除策略

  在redis中,对于过期的键,删除策略有两种,第一种是被动删除,就是在访问设置了过期时间的key时,首先判断该key是否过期,如果该key已经过期,则删除。但是这种方式存在的问题就是没法删除长时间没访问到的key。第二种是主动删除,redis从设置了过期时间的键中选取一部分,将过期的键删除。

4.redis的持久化

  在redis中支持两种持久化的方式,一种是RDB,另一种是AOF(append-only-file)。其中RDB的方式是根据指定的规则将数据库中的数据存储下来,而AOF的方式是定时的将数据库的操作命令记录下来。

  RDB方式:当满足一定的条件时,redis会fork一个子进程来进行持久化,会先将数据存储在一个临时文件中,等到持久化过程结束后,替换原先的持久化文件。该方式的优点是持久化的线程是fork出来的,不会对服务的性能产生影响。但是缺点是最后一次持久化的数据可能会丢失。RDB会在下面几种条件下对数据进行快照,第一是根据配置规则进行自动快照,第二是执行save或bgsave命令,第三是执行flushall命令,第四是执行复制(replication)命令。

  AOF方式:当使用redis存储非临时文件时,为了防止数据的损失,采用AOF的方式是必要的。这种方式是将redis的每一条写命令追加到硬盘文件中,这种方式对redis的性能会有影响,但是这种性能损耗在一定条件下是可以接受的,另外使用较快的硬盘可以提高redis的性能。

5.redis的内存回收策略

随着redis中存储的数据增多,当内存不足时,就需要淘汰一部分的数据,具体的淘汰规则有下面几种。

  第一种:noeviction,默认的策略,当内存不足时,所有申请内存的相关操作都会报错。

  第二种:allkeys-lru,从数据集(server.db[i].dict)中挑选最近最少使用的数据进行淘汰。使用场景:如果我们对缓存的访问都是热点数据,可以使用这个策略。

  第三种:allkeys-random,随机移除某个key。使用场景:如果我们的应用对于缓存key的访问频率相等,可以使用这个策略。

  第四种:volatile-random,从已设置过期时间的数据集(server.db[i].expires)中选取任意的数据进行淘汰。

  第五种:volatile-lru,从已设置过期时间的数据集(server.db[i].expires)中选取最近最少使用的数据进行淘汰。

  第六种:volatile-ttl,从已设置过期时间的数据集(server.db[i].expires)中选取将要过期的数据进行淘汰。

  总结:实际上Redis实现的LRU并不是可靠的LRU,也就是名义上我们使用LRU算法淘汰内存数据,但是实际上被淘汰的键并不一定是真正的最少使用的数据,这里涉及到一个权衡的问题,如果需要在所有的数据中搜索符合条件的数据,那么一定会增加系统的开销,Redis是单线程的,所以对于耗时的操作会谨慎一些。为了在一定成本内实现相对的 LRU,早期的Redis版本是基于采样的LRU,也就是放弃了从所有数据中搜索解改为采样空间搜索优解。Redis3.0 版本之后,Redis作者对于基于采样的LRU进行了一些优化,目的是在一定的成本内让结果更靠近真实的LRU。

6.redis单线程效率高的原因

  redis是单线程的,通过单线程来处理所有来自客户端的请求。redis把所有的任务封装在了一个线程之中,从而避免了线程安全问题。至于为什么要使用单线程,官网认为redis的主要瓶颈在于内存和带宽,而不是cpu。

  redis是跑在单线程中的,所有的操作都是按照顺序线性执行的。但是由于读写操作等待用户的输入输出都是阻塞的,所以IO操作在一般情况下不能够直接返回,这会导致某一文件的IO阻塞,从而使整个进程无法对外提供服务,而IO的多路复用就是为了解决这个问题而出现的。

  几种简单的IO模型,第一种是同步阻塞IO(Blocking IO),即传统IO模型。第二种是同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO需要设置socket为NONBLOCK。第三种是多路复用(IO Multiplexing),即经典的reactor设计模式,也称为异步阻塞IO,java中的selector和linux的epoll都是这种模型。第四种是异步IO(Asynchronous IO),即经典的Proactor设计模式,也称为异步非阻塞IO。

  同步和异步指的是用户线程和内核的交互方式。阻塞和非阻塞指用户线程调用内核IO操作是阻塞还是非阻塞。

7.lua脚本在redis中的使用

7.1 1ua脚本产生的背景

  在我们使用redis的时候,会面临一些问题,第一是原子性问题,redis虽然是单线程的,但是仍然会存在线程安全问题,不过这个问题不在于redis服务器的内部。redis作为数据服务器,是提供给多个客户端使用的,多个客户端相当于同一个进程内的多个线程,如果多个客户端之间没有做好数据同步的策略,就会产生数据的不一致问题。比如,多个客户端的命令没有做请求同步,导致实际的执行顺序可能会不一致,最终的结果也就没法满足原子性了。第二个是效率问题,由于redis是基于内存的数据库,所以它自身的吞吐量是非常高的。但是在实际的使用过程中有一个因素会影响吞吐量,那就是网络。当我们在使用redis做某些特定功能的时候,可能需要多个命令或者是多个数据类型的交互才能够完成,这种多次的网络请求对性能的影响是比较大的。redis为此也提供了优化的措施,比如pipeline管道操作,但是管道有一定的局限性,就是执行的多个命令和响应之间是不存在依赖关系的。在这种情况下,我们就需要一些机制能够编写一些具体的业务逻辑的命令,从而减少网络的请求。

7.2 lua脚本

  redis服务器内部本身提供了对lua基本的支持,允许我们将开发好的lua脚本传到redis中执行。redis客户端可以使用lua脚本在服务器端原子性的执行多个命令。使用lua脚本的好处有,第一,减少了网路的开销,我们可以将多个命令放到一个lua脚本中去执行。第二,原子性操作,lua脚本中可以存放多个redis命令,执行过程不会被打断。第三,lua脚本是可复用的,也可以将脚本存储在redis服务端,较少网络传输的开销。

  在redis中如何使用lua脚本。

redis基础篇的更多相关文章

  1. Redis基础篇(二)高性能IO模型

    我们经常听到说Redis是单线程的,也会有疑问:为什么单线程的Redis能那么快? 这里要明白一点:Redis是单线程,主要是指Redis的网络IO和键值对读写是由一个线程来完成的,这也是Redis对 ...

  2. Redis基础篇(三)持久化:AOF日志

    Redis是内存数据库,但是一旦服务器宕机,内存中的数据将会全部丢失. 最简单的恢复方式是从后端数据库恢复,但这种方式有两个问题: 频繁访问数据库,会给数据库带来巨大的压力: 从数据库中读取相比从Re ...

  3. Redis基础篇(四)持久化:内存快照(RDB)

    AOF好处是每次执行只需要记录操作命令,记录量不大.但在故障恢复时,需要逐一执行AOF的操作命令,如果日志很大,恢复就很慢. 今天学习另一种持久化方式:内存快照.内存快照,是Redis某一时刻的状态, ...

  4. Redis基础篇(五)AOF与RDB比较和选择策略

    RDB和AOF对比 关于RDB和AOF的优缺点,官网上面也给了比较详细的说明redis.io/topics/pers- RDB 优点: RDB快照是一个压缩过的非常紧凑的文件,保存着某个时间点的数据集 ...

  5. Redis基础篇(六)数据同步:主从复制

    Redis具有高可靠性,体现在两方面: 一是数据尽量少丢失,通过前面介绍的持久化方式AOF和RDB,在宕机时可以恢复数据. 二是服务尽量少中断,通过副本冗余来实现. 今天我们学习的就是通过主从复制实现 ...

  6. Redis基础篇(七)哨兵机制

    上一篇文章介绍了高可靠方案:主从集群模式.通过主从库的读写分离,来保证服务的可靠性. 当某个从库出现故障时,不影响服务的使用,主库仍然可以处理写命令,其他从库可以处理读命令.但主库发生故障,就不能处理 ...

  7. Redis基础篇(八)数据分片

    现在有一个场景:要用Redis保存5000万个键值对,每个键值对大约是512B,要怎么部署Redis服务呢? 第一个方案,也是最容易想到的,需要保存5000万个键值对,每个键值对约为512B,一共需要 ...

  8. (六)SpringBoot2.0基础篇- Redis整合(JedisCluster集群连接)

    一.环境 Redis:4.0.9 SpringBoot:2.0.1 Redis安装:Linux(Redhat)安装Redis 二.SpringBoot整合Redis 1.项目基本搭建: 我们基于(五) ...

  9. 生产消费者模式与python+redis实例运用(基础篇)

    根据这个图,我们举个简单的例子:假如你去某个餐厅吃饭,点了很多菜,厨师要一个一个菜的做,一个厨师不可能同时做出所有你点的菜,于是你有两个选择:第一个,厨师把所有菜都上齐了,你才开始吃:还有一个选择,做 ...

随机推荐

  1. @EnableFeignClients 注解

    feignClents在spring容器里找不到的原因 当使用的feignClents 来自引用别的工程时,需要指定包名,如果不指定就算使用ComponentScan 扫描也不行 import org ...

  2. 安装Linux虚拟系统

    VMWare创建虚拟机与Linux系统的安装 准备工作:VMWare虚拟机,Linux系统镜像 创建好虚拟机之后就可以进入Bios(Basic input ouput system)界面设置安装引导顺 ...

  3. day正则表达式补充

    # 2.正则 # 方法:findall | match | split | sub# a = 10# print(a.__hash__())# def fn():# pass# print(fn.__ ...

  4. Django Rest Framework(二)

    •基于Django 先创建一个django项目,在项目中创建一些表,用来测试rest framework的各种组件 models.py class UserInfo(models.Model): &q ...

  5. Linux系统安装jdk教程

    本文仅仅适用于刚刚接触Linux系统的童鞋,毕竟本人也才刚刚玩这个东西,在此记录下以便于以后能查阅及其他童鞋能进行参考,本文为原创随笔,如需转发,请标明出处,谢谢: 此处我采用的是用VMware搭建的 ...

  6. (二)jdk8学习心得之Lambda表达式

    二.Lambda表达式 1. 格式 (参数1,参数2,…,参数n)->{方法体} 注意: (参数1,参数2,...,参数n)要与方法接口中的参数一致,但是名字可以不一样. 此外,方法类型接口,有 ...

  7. 用WPS查看两篇word文档异同之处

    写的合同,后期又有修改,电脑里同样名字的合同有好几个版本,不知道有什么不同,怎么办? 打开wps-->[审阅]-->[比较],剩下的按照提示很容易,略...

  8. Centos 利用yum安装卸载软件常用命令[转载]

    一.使用yum安装和卸载软件,有个前提是yum安装的软件包都是rpm格式的. 安装的命令是,yum install ~,yum会查询数据库,有无这一软件包,如果有,则检查其依赖冲突关系,如果没有依赖冲 ...

  9. css进度条

    1.环形进度条 源码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  10. 谈谈JavaScript中继承方式

    聊一聊js中的继承 一.简单继承---使用原型赋值的方式继承,将实例化的对象,赋值给子级的原型 父级构造函数 function Parent(param) { this.name = 'parent' ...