c++问一下图上这个代码哪里错了,还有下面的两个修改都是什么意思?

我们现在是处于大数据时代;

在以前,一个网站的访问量一般不会太大,所以单个数据库就足够了。而且都是静态页面,服务器无压力。

这种情况下:整个网站的瓶颈是什么?

  1. 数据量如果太大,一个机器放不下
  2. 数据的索引(B+ Tree),一个机器内存放不下
  3. 访问量(读写混合),一个服务器承受不了

出现以上三种情况之一,那么就必须晋级

网站80%的情况都在读,每次都要去查询数据库的话就会十分麻烦!为了减轻数据库的压力,我们就可以使用缓存来保证效率!

发展过程:优化数据结构和索引–》文件缓存(IO)–》Memcached(当时最热门的技术)

3,分库分表+水平拆分

本质:数据库(读,写)

早些年MyISAM:表锁,十分影响效率。对人 的要求也越来越高

慢慢使用分库分表来解决写的压力!

MySQL的集群,就是很好的解决了当时的需求。

到现在,MySQL等关系型数据库已经不够用了!数据很大,变化快

MySQL有的使用他来存取一些很大的文件,博客,图片!数据库表很大,效率低!所以要有一种专门处理这些数据的数据库

目前互联网加过的基本模型

用户的个人信息,社交网络,地理位置,用户自己产生的数据,用户日志等等爆发式的增长

这个时候NoSQL就是一个很好的数据库,可以更好的处理以上情况

泛指非关系型数据库的,随着/

  • 下载地址通过官网下载即可


  • 注意:Windows在GitHub上下载(停更很久了)

    Redis推荐都是在Linux服务器上搭建的,我们是基于Linux学习的!

    1. 
      

      georadius 已给定的经纬度为中心,找出某一半径内的元素

      我附近的人?(获取所有附近的人的地址和定位)通过半径来查询!

      
      

geo底层的实现原理就是Zset!我们可以使用Zset命令来操作geo

基数(就是统计一批数据中不重复的元素)= 7,可以接受误差

优点:占用的内存是固定的,2^64不同的元素的基数,只需要占12kb内存!如果要从内存的角度比较的话Hyperloglog首选!

网页的UV(一个人访问一个网站多次,但是还算是一个人访问)

传统的方式,set保存用户的id,然后就可以统计set中的元素数量作为判断标准!
这个方式如果保存了大量用户的id,就会比较麻烦!我们的目的是为了计数,而不是为了保存id。

但是又0.81的出错率

如果允许容错,那么一定可以使用Hyperloglog!

如果不允许容错,那么就是用set或者自己定义的结构

统计用户信息,活跃,不活跃!登录,未登录!打卡,未打卡!两个状态的都可以使用Bitmaps!

Bitmap位图,数据结构!都是操作二进制来记录,就只有0和1两个状态!

使用Bitmap来记录周一到周日的发卡!

启动的时候,通过配置文件来启动的

行家有没有,出手就知道了

  1. 配置文件unit单位,对大小写不敏感!

持久化,在规定的时间内,执行了多少次操作,则会持久化到文件.rdb .aof

redis是内存数据库,如果没有持久化,那么数据就是断电即失的!


REPLICATION 复制,后面主从复制的时候在写

Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。(微信,微博,关注系统!)

Redis客户端可以订阅任意数量的频道。

第一个:消息发送者 ,第二个:频道,第三个:消息订阅者

这些命令被广泛用于构建即时通信应用,比如网络聊天室(chatroom)和实时广播哦,实时提醒等


订阅某频道后, redis-server里维护了一个字典,字典的键就是一个个 频道,而字典的值则是一个链表,链表中保存了所有订阅这个channel的客户端。SUBSCRIBE 命令的关键,就是将客户端添加到给定channel的订阅链表中。

通过PUBLISH命令向订阅者发送消息, redis-server 会使用给定的频道作为键,在它所维护的channel字典中查找记录了订阅这个频道的所有客户端的链表,遍历这个链表,将消息发布给所有订阅者。

阅,当一个key值上进行了消息发布后,所有订阅它的客户端都会收到相应的消息。这一功能最明显的用法就是 用作实时消息系
统,比如普通的即时聊天,群聊等功能。

  • 实时聊天系统(相当于相互关注,将信息回显给所有的人)
  • 订阅,关注系统都是可以的!

稍微复杂一点的可以用中间插件来做MQ

什么是Jedis是Redis官方推荐的java连接工具,使用Java操作的Redis中间件!如果你要使用Java操作redis,那么一定要对Jedis十分熟悉

  • 
     
     
     
     
     
     
     
    
//Jedis 所有的命令就是我们之前学习的所有指令!

所有的api命令,就是我们对应上面学习的指令,一个都没有变化!


这里呢只实现后端的逻辑代码


 
 
 
 
 
 

Jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的线程,使用Jedis pool连接池!更像BIO模式

lettuce:采用netty,实例可以再多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据了,更像NIO模式

//除了基本的操作都可以直接通过redisTemplate操作,比如事务和基本的CRUD

 
 
 
 
 
 

所有的Redis操作其实对于java开发人员来说十分简单,重要的是去理解redis的思想和每一种数据结构的用处

要么同时成功,要么同时失败,原子性!

Redis单体命令式保证原子性的,但是事务不保证原子性!

Redis本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行过程中,会按照顺序执行!

一次性,顺序性,排他性!执行一些命令!

Redis事务没有隔离级别的概念!

所有的命令在事务中,并没有直接被执行!只有发起执行的命令的时候才会被执行!Exec

  • 开启事务(multi)

编译型异常(代码有错!命令有错!),事务中所有的命令都不会执行!

命令错误,所有的操作都失效

运行时异常(1/0),如果事务队列中存在语法性错误,其他命令是可以正常执行的,错误命令会抛出异常

只要不再事务内报错,后面的命令就可以继续执行

监控!Watch(面试常问)

  • 很悲观,认为什么时候都会出问题,无论做什么都会加锁!
  • 很乐观,认为什么时候都没问题,无论什么时候都不会加锁!更新数据的时候判断一下,再次期间是否有人修改过这个数据

测试多线程修改值,使用watch可以当做redis的乐观锁操作

如果修改失败获取最新的数据即可

Reids事务的三大特性

    • 事务中的所有命令都会序列化,按照顺序地执行。事务再执行过程中,不会被其他客户端发送来的命令请求打断。
    • 队列中命令没有提交前都不会实际被执行,因为事务提交如何指令都不会被实际执行
    • 事务中如果由一条命令执行失败,其后的命令仍然会被执行,没有回滚。

9.1.解决计数器和人员记录的事务操作

SecKill_redisByScript(为了解决因乐观锁产生商品存在但是不能卖的情况,从而用LUA脚本语言实现)



  

  

redis是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态就会消失。所以Redis提供了持久化功能!

在主从复制中,rdb就是备用的!从机上面不占用内存
在指定的时间间隔将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,他恢复时是将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程进行持久化,会先将数据写入一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行然后IO操作的。这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那么RDB方式要比AOF方式更高效。RDB的缺点是最后一次持久化后的数据可能会丢失。我们默认的就是RDB,一般情况下不需要修改这个配置
有时候在生产环境我们会对这个文件进行备份

  1. save的规则满足的时候,会自动触发rdb规则
  2. 退出redis,也会生成一个rdb文件

备份就会自动生成一个dump.rdb文件

  1. 只要将rdb文件放入我们redis启动目录就可以,redis在启动的时候就会自动检查dump.rdb恢复其中的数据!

几乎就是他自己默认的配置就够用了

  • 适合大规模的数据恢复!dump.rdb
  • 需要一定的时间间隔进程操作!如果redis意外宕机,这个最后一次修改数据就没有了
  • fork进程·会占用一定的内存空间

将我们所有命令都记录下来,类似于history,恢复的时候就会把这个文件全部在执行一遍!

以日志的形式来记录每个操作,将Redis执行过的所有指令记录下来(读操作不记录),只追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

默认是不开启的,我们需要手动去配置!我们只需要将appendonly改为yes即可开启aof

重启redis就可以生效了!
如果这个aof文件有错位,这个时候redis是启动不起来的,我们需要对这个文件进行修复

如果这个文件可以启动的话就是就证明了文件恢复了

aof默认就是文件无限追加,文件会越来越大
如果aof文件大于64吗,太大了!就会fork一个新的进程将我们的文件重写

  • 每一次修改都是同步的,文件的完整性会更好!
  • 每一秒同步一次,可能会丢失一秒的数据
  • 相对于数据文件来说,aof远远远远高于rdb,修复速度也比rdb慢
  • aof运行的效率也要比rdb慢,所以redis默认的配置就是rdb持久化!
  • RDB持久化方式能够在指定的时间间隔内对你的数据进行快照存储
  • AOF持久化记录方式每次对服务器写的操作,当服务器重启的时候就会重新执行这些命令来恢复原始数据,AOF命令以Redis协议追加保存每次写的擦欧总到文件末尾,Redis还能对文件进行后台重写,是得AOF文件的体积不至于过大
  • 只做缓存,如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化
  • 同时开启两种持久化方式
    • 在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
    • RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件,那要不要只使用AOF呢?作者建议不要,因为RDB更适合用于备份数据库( AOF在不断变化不好备份) , 快速重启,而且不会有AOF可能潜在的Bug ,留着作为-一个万- -的手段。
    • 因为RDB文件只用作后备用途,建议只在Slave,上持久化RDB文件,而且只要15分钟备份一 次就够了,只保留save 900 1这条规则。
    • 如果Enable AOF ,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了,代价一是带来了持续的I0 ,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。只要硬盘许可,应该尽量减少AOF rewrite的频率, AOF重写的基础大小默认值64M太小了,可以设到5G以上,默认超过原大小100%大小重写可以改到适当的数值。
    • 如果不Enable AOF ,仅靠Master-Slave Repllcation(主从复制)实现高可用性也可以,能省掉一 大笔I0 ,也减少了rewrite时带来的系统波动。代价是如果Master/Slave 同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave 中的RDB文件,载入较新的那个,微博就是这种架构。

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader) ,后者称为从节点(slave/follower) ;数据的复制是单向的,只能由主节点到从节点。Master以写为主 , Slave以读为主。

默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点) ,但-一个从节点只能有一一个主节点。

主从复制的作用主要包括:
1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。

2、故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。

3、负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点) , 分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

4、高可用基石:除了.上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

一般来说,要将Redis运用于工程项目中,只使用一台Redis是万万不能(宕机)的,原因如下:

1、从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;

2、从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量 为256G ,也不能将所有内存用作Redis存储内存,一般来说 ,单台Redis最大使用内存不应该超过20G。

电商网站上的商品,一般都是一 次 上传,无数次浏览的,说专业点也就是"多读少写"。

对于这中场景,我们可以使用以下结构:

主从复制,读写分离!80%的情况下都是在进行读操作!减缓服务器压力!架构中经常使用!最低要求是一主二从!

只要在公司中,主从复制就是必须要使用的,因为在真实的项目中不可能使用单机的Redis。

复制三个配置文件,然后修改对应的信息:

默认情况下,每台Redis服务器都是主节点;一般情况下只要配从机就好了!

认老大!一主(79),二从

真实的主从配置应该在配置文件中配置,这样的话是永久的,我们这里使用的是命令,是暂时的

主机可以写,从机不能写只能读!主机中的所有信息和数据,都会自动被从机保存!

测试主机断开连接,从机依旧连接到主机的,但是没有写操作了,这个时候如果主机回来了,从机依旧可以直接获取到主机写的信息

如果是使用命令行配置的主从,如果重启就会变回主机!只要变回从机,立马就会从主机中获取值!

  1. Slave启动成功连接到master后会发送一个sync命令。
  2. Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令, 在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步。
  3. 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
  4. 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步。
  5. 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行。

层层链路是指如果从机太多,可以让第二个从机负责后面从机的主从复制。类似于一个公司最大的boss是老板,但是手下的人太多了,于是又分出了各种职位来继续领到下面的人。

如果没有老大,这个时候能不能选择一个老大出来呢?动手!

如果主机断开了连接,我们可以使用SLAVEOF no one 让自己变成主机!其他节点就可以手动连接到这个最新的主节点(手动)!如果这个时候老大修复了,那就重新配置连接!

换句话说就是,只要之前主机断开连接,别的从机手动变为主机之后,哪怕之前的主机回归,他也没有从机了。

哨兵模式(自动选老大)

主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis从2.8开始正式提供 了Sentinel (哨兵)架构来解决这个问题。

谋朝篡位的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

  • 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器
  • 当哨兵检测到master宕机,会自动将slave切换到master,然后通过发布订阅模式通知其他进程,修改配置文件,让他们切换主机

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,因此我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了一个多哨兵模式。

假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马.上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线

当后面的哨兵也检测到主服务器不可用,并且数量达到-一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线

我们目前的状态是一主二从

  1. 后面的数字1,表示这个主机挂了,slave投票看让谁成为主机,票数最多的成为主机。

如果我们的Master节点断开了,这个时候就会从从机中随机选择一个服务器!(这里有一个投票算法)

如果此时前主机回来了,也只能当从机!

  • 哨兵集群,基于主从复制模式,所有的主从配置优点他都有
  • 主从可以切换,故障也可以转义,系统的可用性就会更好
  • 哨兵模式就是主从模式的升级,手动到自动,更加健壮!
  • Redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦了!
  • 实现哨兵模式的配置其实很麻烦,这里有很多的选择

C++ 编程语言已经不是用来构建数据库的最佳选择了吗?

其博客文章显示,RisingWave 开源后就很快成为了“使用 Rust 编写的第一大热门项目”。

2021 年初开始构建该数据库时,RisingWave 团队选择了用 C++ 来实现自己的新一代的流式数据库。当时的创始团队由多位具有 10 年以上相关经验的资深 C++ 工程师组成。

随着公司规模扩大,工程师人员的增加,他们开始被 C++ 的“缺点”所困扰:代码可读性差、存在内存泄露和 segmentation fault 等。于是,经过约 7 个月的开发阶段后,团队开始有了质疑:“C++ 语言是编写新数据库系统的正确选择吗?”

C/C++ 无疑是用于构建数据库系统的最流行的编程语言之一,大多数著名的数据库系统都是用 C/C++ 创建的。因此对于这么一家从零开始构建大规模数据库系统的早期创业公司来说,既然大量的数据库是用 C/C++ 构建的,那么它就已被证明是一种可行的系统编程语言;除此之外,C++ 还为开发人员提供了开发高性能程序的机会,提供了对内存和计算的细粒度控制。

虽然 C++ 为程序员提供了很大的灵活性,但它是有代价的。非常容易写出 bug,还极其难以调试,尤其是并发编程。

依赖管理可能很麻烦。虽然如 CMake 工具可以自动配置 C++ 项目的编译,但开发者仍然需要手动配置和安装依赖库。

STL 库缺乏对一些现代编程工具的支持,依赖的社区项目大多数还都缺乏长期支持。

质量保证具有挑战性。C++ 支持的特性如此之多,以至于不同的开发人员可以以截然不同的风格编写 C++。不同背景的开发人员在一个团队中,保持代码可读性有困难。此外,C++ 代码中的 bug 很难识别,因此审查代码会变得令人生畏。

另外,流式数据库通常用于对延迟非常敏感的关键任务。因此只能使用以下语言构建 RisingWave:保证零成本抽象,不会有性能上限;不需要运行时垃圾收集,可以控制可能由内存管理引起的延迟峰值。

考虑到这两个性能目标,经过一个月的讨论之后,RisingWave 做出了从 C++ 迁移到 Rust 的决定。

虽然 Rust 也含有不好的一面,比如“碎片化的异步生态系统、繁琐的错误处理”等,但出于“安全、易于使用、易于学习、易于管理”四大原因,所以 RisingWave 认为 Rust 是一个更好的选择,可以减轻开发人员的精神负担,为高效的大规模协作铺平道路。

我要回帖

更多关于 c++程序错误怎么找 的文章

 

随机推荐