不支持redis是什么意思,第1张

不支持redis是不支持缓存,分布式锁、消息队列。在实际项目中Redis常被应用于做缓存,分布式锁、消息队列等。Redis是一个字典结构的存储服务器,一个Redis实例提供了多个用来存储数据的字典,客户端可以指定将数据存储在哪个字典中。这与在一个关系数据库实例中可以创建多个数据库类似,可以将其中的每个字典都理解成一个独立的数据库。

最近学习了一下Redis写一篇文章来总结一下学习成果,学习的方式主要是看书,看的是Redis 5设计与源码分析;想系统学习的同学,可以好好看看很推荐这本书,那么,为什么标题选择Redis为什么会那么快?因为,我在学习的过程中,感受到Redis的精髓就是快,为了快这个属性,它有了很多自己特殊设计及实现;

Redis快,我主要是基于三大部分的理解

下面分别对这2,3部分进行展开:

首先,先要知道Redis工作线程是单线程的,但是,整个Redis来说,是多线程的;

Redis事件处理 :

Redis 服务器是典型的事件驱动程序,而事件又分为文件事件(socket 的可读可写事件)与时间事件(定时任务)两大类。已经注册的文件事件存储在event[]数组中, 时间事件形成链表;Redis 底层可以使用4中I/O多路复用模型(kqueue、epoll、select等)根据操作系统的不同选择不同, 关于,多路复用模型相关内容可以查看我的另一篇文章 操作系统IO进化史 所以,epoll本身就效率很高了;但是,随着我们网卡的不断升级,在Redis 60之后的版本中,对IO的处理变成了多线程;

为什么对IO的处理变成了多线程能提高速度?

下面是Redis60之前的情况:

如果到了Redis60之后:

所以,这也是Redis快的一个主要原因;

由于,Redis中设计的话,主要分为底层设计结构以及一些相应的功能,所以,特定将其分为2部分来进行讲解;

Redis底层数据结构有简单动态字符串,跳跃表,压缩列表,字典,整数集合;针对,简单动态字符串,压缩列表,主要是考虑到节约内存;像跳跃表,字典,主要是考虑到查询速度,整数集合即考虑到了空间又考虑到了时间;其实像字典中的渐进式rehash,以及间断key查找,都是考虑到了节约时间;具体的内容可以查看我的另一篇文章, Redis底层数据结构

具体细节可查看官网

优点:最多有25%的过期key存在内存中,这种方法会比轮询更加省时间;就是稍微牺牲内存,来保证 redis的性能,就是快; 还是以空间换时间的思想;

注意 :个人觉得这里和 缓存雪崩 还能建立其联系,如果,一个大型的redis实例中所有的key在同一时间过期了,那么,redis会持续扫描keys 因为,一直大于25%;虽然,这是有扫描时间的上限的25ms;这个时候,刚好客户端请求过来了,如果,客户端将超时时间设置的比较短,比如说10ms,那么就会出现大量链接因为超时而关闭,业务端也会出现很多异常。(客户端超时时间,如果说设置得太小,那么容易导致访问redis失败,如果,设置太大,那么,在redis异常的时候,不容易及时作出切换;一般是通过网络延迟和redis慢日志来进行查看的)

redis的特点是快,它虽然有事务,但是,它是没有回滚的,事务的功能是不够完善的; 回滚:代表失败时,回滚到事务开始的时刻;

redis 是单线程的 如果,有多个客户端,一个客户端的事务 并不会阻塞到其他客户端; 客户端1 发送 开启事务的标记 客户端2 也开启事务 。随着时间发展;2又连续发了一些命令 1 也发了一些命令; 这时候,会先看谁的执行指令先到; 假设 2 先到达,这个时候,先执行2 的相关数据,在执行1相关的命令; 如果 1 先到达,这个时候,先执行1 的相关命令,再执行2;

事务失败处理

这个时候,会发现报错那条语句不执行,剩下的语句都会进行执行;也没有发生了回滚;

证明 :redis是不支持事务回滚的。在运行期错误,即使事务中有某条/某些命令执行失败了,事务队列中的其他命令仍然会继续执行 -- Redis 不会停止执行事务中的命令;

为什么Redis 不支持事务回滚?

总结 :Redis为了快,而不支持事务回滚;

在redis中,有两个东西 第一个为RDB 第二个为AOF RDB为快照/副本相关内容, AOF为日志相关的内容;

RDB的特点 :1需要时点性 (比如说:我有1G的内存,需要持久化到硬盘,比如说:一个小时持久化一次。那么,假设在8点,就需要进行持久化)

如何实现RDB持久化呢?

方法一:阻塞Redis ,Redis不再对外提供服务了,但是,这种方式是需要阻塞的,很显然,如果,这个持久化需要花费1s,那么,这个时候,Redis 不能被客户端进行使用;

方法二:非阻塞 Redis继续对外提供服务;

但是,这个时候会出现一个问题;比如说:8点开始RDB持久化,8点零1秒才持久化完,问题就来了:持久化的数据是8点的还是8点零1秒的呢?很显然,是8点的;那么,在8点到8点零1秒这个过程中,数据是会发生改变的,那么, 怎么解决这个数据不一致的问题呢? 比如说:8点的时候,b = 10 到 8点零1秒的时候,b =20;

为了解决这个读写并存 使用CopyOnWrite 的思想来进行实现;

就是,在操作系统中,先使用fork() 创建子线程来复制一份副本(注意:这里拷贝的是指针,所以,速度会很快)然后,这个副本,就保持在8点不变了。然后,复制的时候,就复制这份副本就行了,对数据增删改查就在父进程中更改。

但是,因为父子进程都指向的是同一个内存,所以,不能在这个内存中改,比如说:不能在原来key 8 中进行更改,比如说要改key = 10 那么,就得在内存中,再创建一块区域,然后,让父进程中指针指向新的key ,这样两个进程就不会相互影响了。

这里也验证了Redis是多线程的;

具体实现:

RDB的缺点

RDB的优点 :恢复数据的速度相对较快;

Redis内存大小选择 进程一般使用10G以内,因为从内存到磁盘持久化这个过程,如果说,10G需要写的时间比较久,那么,如何解决呢?1 减少内存 2 硬盘选择固态硬盘;

针对RDB容易丢失数据的问题,提出了AOF持久化机制

AOF : append on File 向文件中,进行追加;redis发生写操作时,会记录到文件中;

优点 :1丢失的数据比较少

背景 :RDB和AOF可以同时开启,如果,开启了AOF只会用AOF来进行恢复,即便RDB也开启了,也不会使用它;因为,AOF的修复比较准确;但是,AOF是比较慢的,所以,在40以后,AOF就包含了RDB全量,和增加的新的写操作。这样来提高速度;

缺点 :由于,AOF是增加的方式,所以,如果一直增加的话,就会有 1体量无限变大 2恢复慢 的缺点;为了解决这个问题,需要设计出一个方案让日志AOF足够小;这个,就有了 重写 的方案;40之前,重写方案是将AOF进行瘦身,比如说:把创建key和删除key的命令进行抵消删除;40之后,就采用 混合持久化 比如说:我这个AOF已经到了100M文件了,这个时候,我先将老的数据变成RDB文件(二进制文件)然后,再存储到AOF中,再将增量以指令的方式Append 到AOF。所以,是一个混合体;这里的AOF日志不再是全量的日志,而是持久化开始到持久化结束这段时间的增量AOF日志通常很小;那么,它这么改变的 优点 是:在Redis重启时,可以先加载RDB的内容,在加载增量AOF日志,完全替代AOF全量日志重放,重启的效率将大幅度提升; 每次一重写完,就会变成RDB

脏数据刷入时机 :AOF日志是以文件形式存在的,当程序对AOF日志进行写操作时, 实际上是先将数据写到一个内存缓存中,然后,让内存再把脏数据写回到磁盘中 那么,什么时候写呢?如果,还没来的及写就宕机了,那么可能会出现日志丢失;这时候有三个级别可以调;

no : 不调用fsync 等到它满了再进行调用(fsync 可以将指定文件的内容,强制从内核缓存刷到磁盘) 一般生产环境不用

always :每写了一个数据,就调用一次fsync 一般生产环境不用

everysec: redis每一秒调用一次flush

一般Redis 的主节点不会进行持久化操作,持久化操作主要是在从节点中进行。因为,没有来自客户端请求的压力;

上面是Redis持久化的两种方式 由于,持久化过程需要花费的时间是比较多的,所以,一般由从节点来进行持久化操作; 主服务器发现需要执行完整重同步时,会fork子进程执行RDB持久化,并将持久化数据发送给从服务器。这时候,有两种选择 1 直接通过Socket发送给从服务器(从服务器支持eof),2 持久化数据到本地文件,待持久化完毕后再将该文件发送给从服务器。 默认第二种,具体情况是根据同步信息确定;但是,第一种效率会更高,速度会更快;

总结 :为了Redis快的特性,Redis在持久化的时候,使用fork()函数,新开线程来执行;同时,如果主从服务器的话,还提供了psync2来进行部分重同步;eof功能;

redis的特点就是快,在系统设计的方方面面都体现了这个快的特性;这是我自己在学习Redis相关知识时,了解到的内容,做个记录。如果,有偏差欢迎读者进行指正!

第一:Redis 是什么?

Redis是基于内存、可持久化的日志型、Key-Value数据库 高性能存储系统,并提供多种语言的API

第二:出现背景

数据结构(Data Structure)需求越来越多, 但memcache中没有, 影响开发效率

性能需求, 随着读操作的量的上升需要解决,经历的过程有: 

数据库读写分离(M/S)–>数据库使用多个Slave–>增加Cache (memcache)–>转到Redis

解决写的问题: 

水平拆分,对表的拆分,将有的用户放在这个表,有的用户放在另外一个表;

可靠性需求 

Cache的"雪崩"问题让人纠结 

Cache面临着快速恢复的挑战

开发成本需求 

Cache和DB的一致性维护成本越来越高(先清理DB, 再清理缓存, 不行啊, 太慢了!) 

开发需要跟上不断涌入的产品需求 

硬件成本最贵的就是数据库层面的机器,基本上比前端的机器要贵几倍,主要是IO密集型,很耗硬件;

维护性复杂 

一致性维护成本越来越高; 

BerkeleyDB使用B树,会一直写新的,内部不会有文件重新组织;这样会导致文件越来越大;大的时候需要进行文件归档,归档的操作要定期做; 

这样,就需要有一定的down time;

基于以上考虑, 选择了Redis

第三:Redis 在新浪微博中的应用

Redis简介

1 支持5种数据结构

支持strings, hashes, lists, sets, sorted sets 

string是很好的存储方式,用来做计数存储。sets用于建立索引库非常棒;

2 K-V 存储 vs K-V 缓存

新浪微博目前使用的98%都是持久化的应用,2%的是缓存,用到了600+服务器 

Redis中持久化的应用和非持久化的方式不会差别很大: 

非持久化的为8-9万tps,那么持久化在7-8万tps左右; 

当使用持久化时,需要考虑到持久化和写性能的配比,也就是要考虑redis使用的内存大小和硬盘写的速率的比例计算;

3 社区活跃

Redis目前有3万多行代码, 代码写的精简,有很多巧妙的实现,作者有技术洁癖 

Redis的社区活跃度很高,这是衡量开源软件质量的重要指标,开源软件的初期一般都没有商业技术服务支持,如果没有活跃社区做支撑,一旦发生问题都无处求救;

Redis基本原理

redis持久化(aof) append online file: 

写log(aof), 到一定程度再和内存合并 追加再追加, 顺序写磁盘, 对性能影响非常小

1 单实例单进程

Redis使用的是单进程,所以在配置时,一个实例只会用到一个CPU; 

在配置时,如果需要让CPU使用率最大化,可以配置Redis实例数对应CPU数, Redis实例数对应端口数(8核Cpu, 8个实例, 8个端口), 以提高并发: 

单机测试时, 单条数据在200字节, 测试的结果为8~9万tps;

2 Replication

过程: 数据写到master–>master存储到slave的rdb中–>slave加载rdb到内存。 

存储点(save point): 当网络中断了, 连上之后, 继续传 

Master-slave下第一次同步是全传,后面是增量同步;、

3 数据一致性

长期运行后多个结点之间存在不一致的可能性; 

开发两个工具程序: 

1对于数据量大的数据,会周期性的全量检查; 

2实时的检查增量数据,是否具有一致性;

对于主库未及时同步从库导致的不一致,称之为延时问题; 

对于一致性要求不是那么严格的场景,我们只需要要保证最终一致性即可; 

对于延时问题,需要根据业务场景特点分析,从应用层面增加策略来解决这个问题; 

例如: 

1新注册的用户,必须先查询主库; 

2注册成功之后,需要等待3s之后跳转,后台此时就是在做数据同步。

第四:分布式缓存的架构设计

1架构设计

由于redis是单点,项目中需要使用,必须自己实现分布式。基本架构图如下所示:

2分布式实现

通过key做一致性哈希,实现key对应redis结点的分布。

一致性哈希的实现:

l        hash值计算:通过支持MD5与MurmurHash两种计算方式,默认是采用MurmurHash,高效的hash计算

l        一致性的实现:通过java的TreeMap来模拟环状结构,实现均匀分布

3client的选择

对于jedis修改的主要是分区模块的修改,使其支持了跟据BufferKey进行分区,跟据不同的redis结点信息,可以初始化不同的 ShardInfo,同时也修改了JedisPool的底层实现,使其连接pool池支持跟据key,value的构造方法,跟据不同 ShardInfos,创建不同的jedis连接客户端,达到分区的效果,供应用层调用

4模块的说明

l        脏数据处理模块,处理失败执行的缓存操作。

l        屏蔽监控模块,对于jedis操作的异常监控,当某结点出现异常可控制redis结点的切除等操作。

整个分布式模块通过hornetq,来切除异常redis结点。对于新结点的增加,也可以通过reload方法实现增加。(此模块对于新增结点也可以很方便实现)

对于以上分布式架构的实现满足了项目的需求。另外使用中对于一些比较重要用途的缓存数据可以单独设置一些redis结点,设定特定的优先级。另外对 于缓存接口的设计,也可以跟据需求,实现基本接口与一些特殊逻辑接口。对于cas相关操作,以及一些事物操作可以通过其watch机制来实现。

声明:所有博客服务于分布式框架,作为框架的技术支持及说明,框架面向企业,是大型互联网分布式企业架构,后期会介绍linux上部署高可用集群项目。

zabbix:是一套服务器性能监控软件,这个没怎么用过,没有发言权。

redis:你可以当成是数据库,和MYSQL差不多(实际上差很多)

nginx:是一个web 服务器,提供网页服务(如果它坏了,用户输入域名就不能正常访问网站)

memcached:基于内存的分布式缓存系统,是redis的长江前浪。

这几个东西和PHP都没关系,但可以这样理解:

nginx 可以做php的WEB服务器

redis 可以做php的数据库或缓存

memcached 可以做PHP的缓存

zabbix 既然能监控服务器性能,能把他们全都监控起来?

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » 不支持redis是什么意思

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情