Redis和MySQL如何保持数据最终一致性

Redis和MySQL如何保持数据一致性?

在高并发的场景下,大量的请求直接访问Mysql很容易造成性能问题。所以,我们都会用Redis来做数据的缓存,削减对数据库的请求。但是,Mysql和Redis是两种不同的数据库,如何保证不同数据库之间数据的一致性就非常关键了。

1、导致数据不一致的原因

1、在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。

2、所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库。

3、读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一致性问题。

4、这个业务场景,主要是解决读数据从Redis缓存,一般都是按照下图的流程来进行业务操作。

1.1、缓存先后删除问题

不管是先写MySQL数据库,再删除Redis缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。

1.2、先删除缓存

1、如果先删除Redis缓存数据,然而还没有来得及写入MySQL,另一个线程就来读取。

2、这个时候发现缓存为空,则去Mysql数据库中读取旧数据写入缓存,此时缓存中为脏数据。

3、然后数据库更新后发现Redis和Mysql出现了数据不一致的问题。

1.3、后删除缓存

1、如果先写了库,然后再删除缓存,不幸的写库的线程挂了,导致了缓存没有删除

2、这个时候就会直接读取旧缓存,最终也导致了数据不一致情况

3、因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题

2、解决方案

2.1、延时双删策略

2.1.1、基本思路

在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。

伪代码如下:

public void write( String key, Object data ){ redis.delKey( key ); db.updateData( data ); Thread.sleep( 500 ); redis.delKey( key );}br

2.1.2、具体步骤

1、先删除缓存

2、再写数据库

3、休眠xxx毫秒(根据具体的业务时间来定)

4、再次删除缓存

问题:这个500毫秒怎么确定的,具体该休眠多久时间呢?

1、需要评估自己的项目的读数据业务逻辑的耗时。

2、这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。

3、当然这种策略还要考虑redis和数据库主从同步的耗时。

4、最后的的写数据的休眠时间:则在读数据业务逻辑的耗时基础上,加几百ms即可。

比如:休眠1秒。

2.1.3、设置缓存过期时间是关键点

1、从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案

2、所有的写操作以数据库为准,只要到达缓存过期时间,缓存删除

3、如果后面还有读请求的话,就会从数据库中读取新值然后回填缓存

2.1.4、方案缺点

结合双删策略+缓存超时设置,这样最差的情况就是:

1、在缓存过期时间内发生数据存在不一致

2、同时又增加了写请求的耗时。

2.1.5、问题

为什么要双删呢!

因为第一次删除的是还没更新前的数据,第二次删除则是因为读取的并发性导致的缓存重新写入数据出现的垃圾数据。

如果你们的删缓存失败了,怎么办?那不是还是会出现缓存和数据库不一致的情况么?比如一个写数据请求,然后写入数据库了,删缓存失败了,这会就出现不一致的情况了。

这时候我们就需要一个中间件的无私配合了,那就是使用消息来进行重试机制。

步骤:

1、业务代码去更新数据库

2、数据库的操作进行记录日志。

3、订阅程序提取出所需要的数据以及key

4、获得该信息尝试删除缓存,发现删除失败的时候,发送消息到消息队列

5、继续重试删除缓存的操作,直到删除缓存成功。

其实这个方法与分布式事务的处理方式,就是保证数据的最终一致性,而在分布式事务中,则称之为这种为最大努力通知。那么最大努力通知又是什么样的流程呢?

1、业务方把通知发送给 MQ

2、接收通知方监听 MQ

3、接收通知方接收消息,业务处理完成回应ack

4、接收通知方若没有回应ack则MQ会重复通知,MQ 按照间隔时间从短到长的方式逐步拉大通知间隔,直到达到通知要求的时间上限,比如24小时之后不再进行通知。

5、接收通知方可通过消息校对接口来校对消息的一致性

总结:

而为什么叫最大努力通知呢,实际上也很容易理解,他并没有从本质上解决问题,只是把问题数目从100 变成了 10 ,毕竟有些内容第一次没处理,第二次就可能会被处理掉。也就是说降低了这种有问题情况的发生,毕竟保证的都是最终一致性。

2.2、异步更新缓存(基于Mysql binlog的同步机制)

2.2.1、整体思路

1、涉及到更新的数据操作,利用Mysql binlog 进行增量订阅消费

2、将消息发送到消息队列

3、通过消息队列消费将增量数据更新到Redis上

4、操作情况

读取Redis缓存:热数据都在Redis上

写Mysql:增删改都是在Mysql进行操作

更新Redis数据:Mysql的数据操作都记录到binlog,通过消息队列及时更新到Redis上

2.2.2、Redis更新过程

数据操作主要分为两种:

1、一种是全量(将所有数据一次性写入Redis)

2、一种是增量(实时更新)

这里说的是增量,指的是mysql的update、insert、delate变更数据。

读取binlog后分析 ,利用消息队列,推送更新各台的redis缓存数据。

1、这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis

2、Redis再根据binlog中的记录,对Redis进行更新

3、其实这种机制,很类似MySQL的主从备份机制,因为MySQL的主备也是通过binlog来实现的数据一致性

这里的消息推送工具你也可以采用别的第三方:kafka、rabbitMQ等来实现推送更新Redis!

3、总结

在高并发应用场景下,如果是对数据一致性要求高的情况下,要定位好导致数据和缓存不一致的原因。

解决高并发场景下数据一致性的方案有两种,分别是延时双删策略和异步更新缓存两种方案。

也可以采用别的第三方:kafka、rabbitMQ等来实现推送更新Redis!

本文转载于网络 如有侵权请联系删除

相关文章

  • H5网页播放器EasyPlayer.js如何实现直播视频实时录像?

    EasyPlayer系列做了整整8年了,从最开始的EasyPlayerRTSP版,到后来的RTMP版、Pro版、js版,受众用户已经不计其数了,希望EasyPlayer能一如既往地优秀下去。最近,有位用户对我们的EasyCVR提出了一种关于播放器实时录像的需求。按照以往的概念,网页怎么能像C/S客户端那样做实时的视频录像呢?因为浏览器写本地文件几乎是不可能的一件事情。在以往的做法中,实现这种用户需求,基本上也就是采用“后端+前端”配合的方式来实现这种录像功能。后端收到前端录像的指令,将要发往前端的音视频数据先预存一份在服务端,当收到前端的停止录像指令后,再将整个缓存的数据,打包封装成MP4,提供给用户下载。事实上,这种方式其实是非常不合理的。试想一下,如果有成千上万的用户在使用这个功能,服务端不但要缓存数据,还要封装数据,还要维护Session和Download数据(实际这个数据已经从直播输出给客户端一次了)。这种做法既是一种流量的浪费,又是计算资源的浪费,不符合技术开发者的工匠思想。对于“后端+前端”这种不合理的实时录像方式,我们要想办法改善,采用更为合理的“去中心化”做法。于是,经

  • 域名解析和cdn 原理

    用户访问未使用CDN缓存网站的过程为:  1)、用户向浏览器提供要访问的域名;  2)、浏览器调运维 用户访问未使用CDN缓存网站的过程为:1)、用户向浏览器提供要访问的域名;2)、浏览器调用域名解析函数库对域名进行解析,以得到此域名对应的IP地址;3)、浏览器使用所得到的IP地址,域名的服务主机发出数据访问请求;4)、浏览器根据域名主机返回的数据显示网页的内容。使用了CDN缓存后的网站的访问过程变为:1)、用户向浏览器提供要访问的域名;2)、浏览器调用域名解析库对域名进行解析,由于CDN对域名解析过程进行了调整,所以解析函数库一般得到的是该域名对应的CNAME记录,为了得到实际IP地址,浏览器需要再次对获得的CNAME域名进行解析以得到实际的IP地址;在此过程中,使用的全局负载均衡DNS解析,如根据地理位置信息解析对应的IP地址,使得用户能就近访问。3)、此次解析得到CDN缓存服务器的IP地址,浏览器在得到实际的IP地址以后,向缓存服务器发出访问请求;4)、缓存服务器根据浏览器提供的要访问的域名,通过Cache内部专用DNS解析得到此域名的实际IP地址,再由缓存服务器向此实际IP地址

  • Go语言基础之time包详解

    前言一寸光阴一寸金,时间难买寸光阴,时间,是个多么重要的东西。同样,在我们的编程中,时间也依然占据着很大的一部分。就像淘宝,客户下单需要记录时间,发货了需要记录时间,保质期多久需要推算时间,等等等等。那我们一起来看看Go中是如何操作时间叭!time.Now()time.Now()返回的是一个Time类型。相关代码如下funcmain(){ varnowTime=time.Now() fmt.Println(nowTime) varyear=nowTime.Year()//当前年份 varmonth=nowTime.Month()//当前月份 varday=nowTime.Day()//今天几号 varhour=nowTime.Hour()//现在几时 varMinute=nowTime.Minute()//现在几分 varsecond=nowTime.Second()//现在几秒 fmt.Printf("当前年份:%v\n",year) fmt.Printf("当前月份:%v\n",month) fmt.Printf("几号了:%v\n

  • What is the Memory Model in C++11

    C++11其实主要就四方面内容,第一个是可变参数模板,第二个是右值引用,第三个是智能指针,第四个是内存模型(MemoryModel)。 相对来说,这也是较难理解的几个特性,分别针对于泛型编程,内存优化,内存管理和并发编程。并发编程是个非常大的模块,而在诸多内容底下有一个基本的概念,就是并发内存模型(MemoryModel)。 那么,什么是内存模型?1MemoryModel早在之前介绍并发编程的文章中,我们就知道同步共享数据很重要。而同步可分为两种方式:原子操作和顺序约束。原子操作是数据操作的最小单元,天生不可再分;顺序约束可以协调各个线程之间数据访问的先后顺序,避免数据竞争。 通常的同步方式会有两个问题,一是效率不够,二是死锁问题。导致效率不够是因为这些方式都是lock-based的。当然,若非非常在意效率,完全可以使用这些同步方式,因其简单方便且不易出错。 若要追求更高的效率,需要学习lock-free(无锁)的同步方式。内存模型,简单地说,是一种介于开发者和系统之间的并发约定,可以无锁地保证程序的执行逻辑与预期一致。这里的系统包括编译器、处理器和缓存,各部分都想在自己的领域对程序进

  • 学习一下Python的垃圾回收

    阅读本文大概需要5分钟。如果你的程序运行一次就退出了,你可能体会不到内存管理的重要性。如果你写的程序需要7x24小时持续不断地运行,那么内存管理就非常重要,尤其对于重要的服务,不能出现内存泄漏。这里的内存泄漏不是出内存出现的数据丢失,或者说内存空间在物理上消失了,而是指程序本身没有设计好,导致占用的内存应该释放出来而实际上没有释放,导致系统可用的内存严重不足,出现系统或服务因此而崩溃。Python是如何进行垃圾回收的呢?换句话说Python是怎么回收不再使用的内存空间的呢?1、如何找到可以回收的内存?众所周知,Python中的万物皆对象,对象占用一定的内存,我们通过变量来访问一个对象,变量的本质,就是对象的一个指针(地址)。如何让我们自己决定回收哪一个对象的空间,很容易想到这样的方法:没有变量指向该对象时,说明它已经没用了,它占用的空间就可以回收。事实上,Python就是这么做的,我们来看一段代码和结果:importos importpsutil #显示当前python程序占用的内存大小 defshow_memory_info(hint): pid=os.getpid() p=psu

  • C++核心准则E.2:通过抛出异常来表明函数无法执行指定的任务

    E.2:Throwanexceptiontosignalthatafunctioncan'tperformitsassignedtaskE.2:通过抛出异常来表明函数无法执行指定的任务 Reason(原因)Tomakeerrorhandlingsystematic,robust,andnon-repetitive.为了使用错误处理系统化,健壮和不繁琐。Example(示例)structFoo{ vector<Thing>v; File_handlef; strings; }; voiduse() { Foobar{{Thing{1},Thing{2},Thing{monkey}},{"my_file","r"},"Herewego!"}; //... } 复制Here,vectorandstringsconstructorsmaynotbeabletoallocatesufficientmemoryfortheirelements,vectorsconstructormaynotbeablecopyth

  • MES系统选项框架

    1.引子 制造执行系统(manufacturingexecutionsystem,简称MES)经历了从最初的生产现场管理(MESA11模块)到c-MES(协同式MES)再到现在转型成MOM(生产运营管理),其在企业信息化中承上启下的作用越来越重要。随着如今工业4.0,制造业升级的浪潮,MES/MOM成为制造业数字化转型的新宠。企业的认可,潜在的市场价值催生了MES市场的繁荣,也同时催生了大量厂商涌入MES市场。面对海量的MES供应商,越来越趋同的MES方案,如何选择MES系统/供应商成为了企业面对的首要问题。俗话说,好的开始是成功的一半,我们看一看如何进行MES系统选型来为MES系统的成功落地打下坚实基础。2.框架组成 选型框架引用PRINCE2项目管理中的BUS模型,它由B-BusinessObjective,U-Superuser,S-Supplier三部分组成。商业目标(BusinessObjective)是项目要实现的终极目标,是项目之所以存在的基础。它需要符合杰里米.边沁的功利主义原理也即“所做事情是否正义的衡量标准是带来的幸福(pleasure)总和大于痛苦(pain)总和

  • 成本更低,百度发布国内首个L4级自动驾驶纯视觉城市道路闭环解决方案

    研发ApolloLite并不代表百度会放弃现有的激光雷达技术方案。策划&撰写:伶轩 近日,百度发布了国内首个L4级自动驾驶纯视觉城市道路闭环解决方案——百度ApolloLite。据百度方面介绍,ApolloLite经过前期研发和今年上半年的路测迭代,已经可以做到10路摄像头、200帧/秒数据量的并行处理,单视觉链路最高丢帧率低于5%,360°实时环境感知,以及前向障碍物的稳定检测视距达240米。简单来说,基于ApolloLite的10路摄像头感知系统,百度无人车已经可以在不依赖高线数旋转式激光雷达的情况下,实现端到端闭环自动驾驶。而且相较于旋转式激光雷达感知方案,因摄像头是相对成熟的传感器,且价格低、符合车规,所以视觉感知方案的成本更低。与此同时,摄像头获取的图像与人眼感知的图像最为接近,较三维点云数据更为直观,对算法、数据积累量、研发投入等的要求也比较低。除此之外,百度Apollo技术委员会主席王亮还表示,“百度一直坚持走多传感器融合的技术路线,因为在L4级自动驾驶传感器选型上,激光雷达和摄像头是同等重要且不可替代的,而不是排它或者从属关系。因此,研发ApolloLite并不

  • leetcode-198-House Robber(动态规划)

    题目描述:Youareaprofessionalrobberplanningtorobhousesalongastreet.Eachhousehasacertainamountofmoneystashed,theonlyconstraintstoppingyoufromrobbingeachofthemisthatadjacenthouseshavesecuritysystemconnectedand itwillautomaticallycontactthepoliceiftwoadjacenthouseswerebrokenintoonthesamenight.Givenalistofnon-negativeintegersrepresentingtheamountofmoneyofeachhouse,determinethemaximumamountofmoneyyoucanrobtonight withoutalertingthepolice.Example1:Input:[1,2,3,1] Output:4 Explanation:Robhouse1(money=1)andt

  • 如何在Kali Linux上发动DDOS攻击

    本次文章发动DDOS攻击的是Github上的Python脚本Paylod:https://github.com/Ha3MrX/DDos-Attack首先从Github克隆到本地:git clone https://github.com/Ha3MrX/DDos-Attack复制然后进入DDos-Attack这个目录:cd DDos-Attack复制接着给ddos-attack.py设置权限:chmod +x ddos-attack.py复制用Python去运行ddos-attack.py这个python脚本:python ddos-attack.py复制我们输入攻击的IP:(用我博客举例子:www.liuwx.cn,端口80):!!!请各位童鞋高抬贵手别D我博客!!!原文由:Web安全攻防实验室

  • PrefixSpan算法原理总结

        前面我们讲到频繁项集挖掘的关联算法Apriori和FPTree。这两个算法都是挖掘频繁项集的。而今天我们要介绍的PrefixSpan算法也是关联算法,但是它是挖掘频繁序列模式的,因此要解决的问题目标稍有不同。1. 项集数据和序列数据    首先我们看看项集数据和序列数据有什么不同,如下图所示。    左边的数据集就是项集数据,在Apriori和FPTree算法中我们也已经看到过了,每个项集数据由若干项组成,这些项没有时间上的先后关系。而右边的序列数据则不一样,它是由若干数据项集组成的序列。比如第一个序列<a(abc)(ac)d(cf)>,它由a,abc,ac,d,cf共5个项集数据组成,并且这些项有时间上的先后关系。对于多于一个项的项集我们要加上括号,以便和其他的项集分开。同时由于项集内部是不区分先后顺序的,为了方便数据处理,我们一般将序列数据内所有的项集内部按字母顺序排序。2.子序列与频繁序列    了解了序列数据的概念,我们再来看看上面是子序列。子序列和我们数学上的子集的概念很类似,也就是说,如果某个序列A所有的项集在序列B中的项集都可以找到,则A就是B的子序列

  • 项目定制-EC616(SLM130,BC260Y,Air302)烧录MQTT透传固件使用说明

    说明美格的SLM130,移远的BC260Y,合宙的Air302,安信可的EC-01等等,里面都是使用的移芯的EC616芯片做的模组.各家的AT指令或者脚本语言开发是在移芯提供的SDK的基础上修改的,就相当于一个芯片各家烧录了各家的程序.所以程序都是通用的.烧录固件1.解压并打开烧录软件2.Prjfile选择3.在第一栏鼠标右键 点击Edititem选择BootLoader文件4.在第二栏鼠标右键 点击Edititem选择mqtt文件5.使用串口模块连接NB模组(SLM130,BC260Y,Air302)串口模块和模组的连接推荐使用下面的方式串口模块      模组(串口1)  TX         RX  RX         TX DTR        RST RTS        BOOT如果只连接了TX和RX引脚,那么把BOOT接低电平,然后复位下模组.模组就会进入烧录固件模式6.点击下载7.下载成功8,复位下模组(模组安装上手机卡和天线),并打开串口助手串口透传也是选择的那个下载口作为的串口透传等待一会看到打印的16进制数据为方便知道模组的状态,规定了一些数据9,通信测试打开M

  • Jenkins Tomcat安装设置

    JenkinsTomcat安装设置 以下为必须满足Jenkins Tomcat设置的先决条件。 第1步:验证安装Java 要验证Java安装,打开控制台并执行以下Java命令。 OS 任务 命令 Windows 打开命令控制台 \>java–version Linux 打开命令终端 $java–version 如果Java已经正确地在系统上安装,那么你应该得到以下输出之一,这取决于您所使用的系统平台。 OS输出 Windows Javaversion"1.7.0_60" Java(TM)SERunTimeEnvironment(build1.7.0_60-b19) JavaHotspot(TM)64-bitServerVM(build24.60-b09,mixedmode) Linux javaversion"1.7.0_25" OpenJDKRuntimeEnvironment(rhel-2.3.10.4.el6_4-x86_64) OpenJDK64-BitServerVM(build23.7-b01,mixedmode

  • 【腾讯敏捷转型No.3】Scrum有什么好?

    在敏捷转型的过程中,除了敏捷宣言中的四个价值观和十二条原则以外,并没有太多比较权威的理论实践。 如图一,敏捷宣言中的四个价值观: (图一) 四条敏捷核心价值观指出了敏捷的核心思想,但是并没有仔细说明具体的实践方法。所以这四个价值观看上去比较抽象,很难理解。下面我分享亲身经历腾讯敏捷转型所遇到的案例,足以说明敏捷宣言中工作的软件高于详尽的文档这条价值观(其余的价值观我会在另外文章里面解释)。 “工作的软件”高于“详尽的文档”。举个例子:“如果买一个崭新的洗衣机回家后,有多少人会看完使用说明书再使用洗衣机洗衣服呢?”对于这个问题,我想,不管男女老少,答案都是一致的:根本不会。因为洗衣机的使用大家都比较熟悉,而且家电行业发展很成熟,所以很多人即使不看说明书,一样懂得如何去操作洗衣机。 而“工作的软件”高于“详尽的文档”也就是这个意思。这里的软件就等同洗衣机,详尽的文档等同于使用说明书,软件的可用性是第一位的,详尽的文档是其次的。同样,在软件开发中,开发团队的重心应该是放在如何保证软件的可用性,而不是思考如何写一个完美的文档。例如:增加软件异常行为监控,增加crash的上报,不断分析用户的行

  • [ML学习笔记] 决策树与随机森林(Decision Tree&amp;Random Forest)

    [ML学习笔记]决策树与随机森林(DecisionTree&RandomForest) ##决策树 决策树算法以树状结构表示数据分类的结果。每个决策点实现一个具有离散输出的测试函数,记为分支。 一棵决策树的组成:根节点、非叶子节点(决策点)、叶子节点、分支 算法分为两个步骤:1.训练阶段(建模)2.分类阶段(应用) ###熵的概念 设用P(X)代表X发生的概率,H(X)代表X发生的不确定性,则有:P(X)越大,H(X)越小;P(X)越小,H(X)越大。 信息熵的一句话解释是:消除不确定性的程度。熵=$-\sum_{i=1}^nP_i\log(P_i)$ 当熵较小时表示集合较纯,分类效果较好。因此,构造树的基本想法是随着树深度的增加,节点的熵迅速降低,降低的速度越快越好,这样才有望得到一棵高度最矮的决策树。 ###如何划分 为了满足上述基本想法,想要选取一个划分标准来为当前集合分类,需要定义一个指标来评判分类效果。 常见的有以下三种指标: ID3:信息增益(划分前熵值-划分后熵值) C4.5:信息增益率(信息增益/划分前的熵值) CART:Gini系数 最传统的做法就

  • 当在scope样式中使用/deep/飘红报错时

    当在scope样式中使用/deep/飘红报错时,可以使用::v-deep代替。 <stylelang="scss"scoped> ::v-deep{ .van-index-anchor{ padding:0; } } </style> 复制 这和/deep/是一样的效果。

  • mybatis之foreach用法

    foreach元素的属性主要有item,index,collection,open,separator,close。 item:集合中元素迭代时的别名,该参数为必选。 index:在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选 open:foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选 separator:元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。 close:foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。 collection:要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array将会失效。除了入参这

  • 人脸检测

    Haar级联分类器 正常人的脸一定具备眼睛、鼻子、嘴巴等特征,每个特征都做成一个专门的检测分类器,所有分类器串起来,全部检测通过则判定为人脸。   分类器下载地址: https://github.com/opencv/opencv/tree/master/data/haarcascades   importcv2 #读取待检测的图像 image=cv2.imread("./111.jpg") cv2.imshow("image",image) #转灰度图 gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) #获取级联分类器对象 faceCascade=cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml') #检测 faces=faceCascade.detectMultiScale(gray,1.3,3) print("发现{}个人脸!".format(len(faces))) #绘制人脸框 for(x,y,w,h)inf

  • /etc/systemd/system 和 /lib/systemd/system 的区别

    /etc/systemd/system和/lib/systemd/system的区别 出处:https://www.cnblogs.com/TonvyLeeBlogs/articles/13762400.html linux系统中有很多的system目录,在平常使用中或者大量的博客中,常看到的有/etc/systemd/system、/lib/systemd/system以及/usr/lib/systemd/system等,这三者有什么样的关系呢,本文将三者的关系详细说明,后续使用不再混淆。 简介 目录/lib/systemd/system以及/usr/lib/systemd/system其实指向的是同一目录,在/目录下执行命令ll即可知: [root@localhost/]#ll total28 lrwxrwxrwx.1rootroot7Jul309:43bin->usr/bin dr-xr-xr-x.5rootroot4096Jul1912:04boot drwxr-xr-x.19rootroot3080Jul1904:03dev drwxr-xr-x.76rootroo

  • 金桥持仓2个月,不如5分钟的涨幅

    昨天的浦东可以立法消息刚出,涨停后两天大幅回落, 今天13.45出了之后,5分钟大涨8毛钱,然后14.59封涨停了了。

  • 详解SESSION与COOKIE的区别

    大家都知道,session是存储在服务器端的,cookie是存储在客户端的。但是问到具体的,还真不太好回答。总结如下: 1.cookie是客户端保持状态的方案,他需要用户打开浏览器的cookie支持,而session机制是服务器端与客户端保持状态的一种方案。 2.session是针对与每一个用户而言的,变量的值存储在服务器上,用sessionID来区别是哪个用户变量,这个值是用户的浏览器返回给服务器的,如果客户禁用cookie,可以通过get方式传递给服务器。就安全性而言,明显session更好。

相关推荐

推荐阅读