当前位置: 首页 > news >正文

Redis集群分片

文章目录

  • 1、Redis集群的基本概念
  • 2、浅析集群算法-分片-槽位slot
    • 2.1 Redis集群的槽位slot
    • 2.2 Redis集群的分片
    • 2.3 两大优势
    • 2.4 如何进行slot槽位映射
    • 2.5 为什么redis集群的最大槽数是16384个?
    • 2.6 Redis集群不保证强一致性
  • 3、集群环境搭建
    • 3.1 主从容错切换迁移
    • 3.2 主从扩容和缩容
  • 4、集群常用操作命令和CRC16算法分析

1、Redis集群的基本概念

前面谈到哨兵的作用就是无人值守运维,无非就是master宕机,slave再顶上去。但此时会有一个大问题, master挂掉后,写操作会被暂时中断,哨兵们需要投票选举新的master,选举新的leader,由leader推动故障切换流程,至此新的master才能对外提供写操作。在老master宕机到新master上位这个前期,redis服务处于一个半瘫痪状态,只能读不能写,就会导致数据流失,这个过程的持续时间可能还会因为硬件、网络等原因增长。因此承受单点高并发的master只有一个是远远不够的。所以Redis就引入了集群

Redis集群:由于数据量过大,单个Master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展每个复制集只负责存储整个数据集的一部分,这就是Redis的集群,其作用是提供在多个Redis节点间共享数据的程序集。

在这里插入图片描述

在这里插入图片描述

Redis集群对外是一个整体,在内部具体是哪一个实例为客户端提供服务与客户端无关。

例如,我打联通客服,人工服务,我只关心是否能够服务,并不关心对应的具体是哪位客服

对应的master宕机了,其他master也能对外提供服务,除此之外slave会上位成为master,也能对外提供服务。因此,Redis集群几乎就替代了原来的主从复制+哨兵监控机制。

一句话就是:Redis集群是一个提供在多个Redis节点间共享数据的程序集

Redis集群能干嘛?

  1. Redis集群支持多个Master,每个Master又可以挂载多个Slave——读写分离、支持数据的高可用、支持海量数据的读写存储操作
  2. 由于Cluster自带SentineI的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
  3. 客户端与Redis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一个可用节点即可
  4. 槽位slot负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系

2、浅析集群算法-分片-槽位slot

2.1 Redis集群的槽位slot

Redis集群没有使用一致性hash,而是引入了哈希槽的概念。Redis集群中内置了16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽集群的每个节负责一部分hash槽。
举个例子,比如当前集群有3个节点,那么:
在这里插入图片描述

redis1负责槽位0-5460,redis2负责槽位5461-10922,redis3负责槽位10923-16383
比如冯同学需要写入一个数据,它的key为fl,经过CRC16运算后,对16384进行取余,假设余数为721,由于721这个槽位是有由redis1负责,那么这个写操作就是由redis1完成,其他redis不能进行写操作,否则会报错。读取操作也是由redis1负责

官方文档说明:
在这里插入图片描述

大致意思:

集群的密钥空间被划分为16384个槽位,有效地设置了集群规模的上限为16384个主节点(然而,节点的最大值建议是大约1000个节点)。

后续会讲到为什么只有16384个槽位,为什么建议最大值为1000个节点

2.2 Redis集群的分片

使用Redis集群时我们会将存储的数据分散到多台redis机器上,这称为分片。简言之,集群中的每个Redis实例都被认为是整个数据的一个分片。

如何找到给定key的分片

这个问题的答案在前面已经给出,但是我还是要再讲一遍,加深印象。
为了找到给定key的分片,我们对key进行CRC16(key)算法处理并通过对总分片数量取模。然后,使用确定性哈希函数,这意味着给定的key将多次始终映射到同一个分片,我们可以推断将来读取特定key的位置。

2.3 两大优势

采用槽位和分片有两大优势:方便扩容和数据分派查找
这种结构很容易添加或者删除节点比如如果我想新添加个节点D,我需要将节点A, B, C中的部分槽转移到D上。如果我想移除节点A,需要将A中的槽转移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态

2.4 如何进行slot槽位映射

哈希取余分区

在这里插入图片描述

2亿条记录就是2亿个k,v, 我们单机不行必须要分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式:hash(key) % N个机器台数,计算出哈希值,用来决定数据映射到哪一 个节点上。

优点:
简单粗暴,直接有效,只需要预估好数据规划好节点,例如3台、8台、10台,就能保证一段时间的数据支撑。使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求 ( 并维护这些请求的信息),起到负载均衡+分而治之的作用。

缺点:
原来规划好的节点,进行扩容或者缩容就比较麻烦了额,不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化:Hash(key)/3会变成Hash(key)/?。此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

一致性哈希

我之前写了一篇博客,可以了解一下,这里就不多赘述----》一致性哈希

哈希槽分区

哈希槽分区的相关概念已经讲过,这里不多赘述。

那么为什么会采用哈希槽分区算法,而不采用其他两种方法呢?
哈希取余的缺点太过明显,就不用说了。而一致性哈希感觉也没啥大毛病,为啥不用一致性哈希算法呢?
一致性哈希算法可以帮助在Redis节点之间平衡数据负载。但它有一个缺点,就是当节点增加或删除时,可能需要重新分配许多键值对,这会导致大量的数据迁移,带来额外的网络开销和延迟。此外,一致性哈希算法在节点故障时也可能导致数据不平衡。

哈希槽架构则更加直接。Redis把数据分成固定数量的哈希槽,每个节点负责一部分哈希槽。当节点增加或删除时,只需将它们的哈希槽重新分配给其他节点即可,这个过程不会涉及到大量的数据迁移。这使得Redis的扩展更加容易和可控,而且在节点故障时也更加稳定。此外,哈希槽架构也更加容易进行备份和恢复操作。

总的来说,哈希槽架构相对于一致性哈希算法来说更加简单、可控、易于扩展和稳定,这也是Redis采用哈希槽架构的原因。

2.5 为什么redis集群的最大槽数是16384个?

CRC16算法产生的hash值有16bit,该算法可以产生2^16=65536个值。换句话说值是分布在0~65535之间,有更大的65536不用为什么只用16384就够?作者在做mod运算的时候,为什么不mod65536,而选择mod16384?HASH_ SLOT = CRC16(key) mod 65536为什么没启用?

看看作者的原话:

在这里插入图片描述

原话翻译:

  1. 正常的心跳包携带一个节点的完整配置,可以用幂等的方式替换旧的配置以更新旧的配置。这意味着它们包含一个节点的插槽配置,以原始形式,使用16k插槽使用2k空间,但使用65k插槽将使用令人难以忍受的8k空间。

  2. 同时,由于其他设计上的权衡,Redis集群不太可能扩展到1000多个主节点。

因此,16k是正确的范围,可以确保每个master有足够的插槽,最多为1000个maters,但这个数字足够小,可以很容易地将插槽配置为原始位图。请注意,在较小的集群中,位图将很难压缩,因为当N很小时,位图会有槽/N位,这是一个很大的百分比。

看不懂没关系:作者的意思可以总结为以下三点:

(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为65536时, 这块的大小是: 65536+8+1024=8kb
在消息头中最占空间的是myslots[CLUSTER_SLOTS/8]。 当槽位为16384时, 这块的大小是: 16384+8+1024=2kb
因为每秒钟,redis 节点需要发送一定 数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。

在这里插入图片描述

(2)redis的集群主节点数量基本不可能超过1000个
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群, 16384个槽位够用了。没有必要拓展到65536个。

(3)槽位越小,节点少的情况下,压缩比高, 容易传输
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率 slots / N很高的话(N表示节点数),bitmap的压缩率就很低。如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。

2.6 Redis集群不保证强一致性

Redis集群不保证强一致性, 这意味着在特定的条件下,Redis集群可能会丢掉一些被系统收到的写入请求命令

例如:当客户端写了三条数据,此时master也写完成,准备给slave同步数据时宕机了,这三条数据就丢失了,slave上位成为master,对外提供服务,此时客户端查看数据时,并没有这三条数据,因此造成了数据不一致

3、集群环境搭建

本次案例我在一台云服务器完成,但实际生产上肯定是搭建在多台云服务器上

整体架构

在这里插入图片描述

在这里插入图片描述

新建6个独立的redis实列服务

在这里插入图片描述

每个.conf文件内容都为,只需要变动6381即可:

bind 0.0.0.0
daemonize yes
protected-mode no
port 6381
logfile "/root/myredis/cluster/c1uster6381.log"
pidfile /root/myredis/clustercluster6381.pid 
dir /root/myredis/cluster
dbfilename dump6381.rdb
appendonly yes
appendfilename "appendon1y6381.aof"
requirepass 123456
masterauth 123456
cluster-enabled yes 	#打开集群
Cluster-config-file nodes-6381.conf	#集群的配置文件叫nodes-6381.conf
cluster-node-timeout 5000	#集群之间的超时时间

在复制上述配置时,后面的中文信息一定要删掉,否则在启动redis实例时,会失败
在这里插入图片描述

启动6台redis主机实例

在这里插入图片描述

使用命令构建主从关系

redis-cli -a fl12345.0 --cluster create --cluster-replicas 1 ip:6381 ip:6382 ip:6383 ip:6384 ip:6385 ip:6386

解释:–cluster-replicas 1表示为每个master创建一个slave节点
在这里插入图片描述

在这里插入图片描述

查看是否生成对应的log和nodes.conf

在这里插入图片描述

链接进入6381作为切入点,查看并检验集群状

在这里插入图片描述
在前面的整体架构图中,主机6381下面是从机6382,但是现在下面却是从机6384,以实际分配为准

可以用命令 cluster nodes 查看集群之间的基本关系

在这里插入图片描述

也可以用命令 cluster info 查看信息

在这里插入图片描述

验证是否能进行读写操作

在这里插入图片描述
为什么插入 k2 v2就行,而插入k1 v1 就失败呢?
因为k1和k2映射的槽位不同,需要到负责对应槽位的redis操作才能成功,也就是说需要路由到位

如何解决?
退出,重新登录,加上参数-c,防止路由失效
在这里插入图片描述

可以看到该操作被重定向到了主机6383

用命令 cluster keyslot key 查看key属于哪个槽位
在这里插入图片描述

3.1 主从容错切换迁移

主机6381停机,从机6384是否能成功上位成为master

在这里插入图片描述

查看集群关系

在这里插入图片描述
三主二从,新master6384没有slave

6381重新启动,是否会再次成为master呢?

在这里插入图片描述
答案是并不会,会以slave的形式回归,它会成为主机6384的slave

在上述过程中,6381从新上位,成了6384的slave,但是我们还是想让6381成为6384的master,如何做?可以使用命令 cluster failover 手动调整节点从属关系

在这里插入图片描述

3.2 主从扩容和缩容

主从扩容

新建6387、 6388两个服务实例配置文件+新建后启动,这里的操作和前面的一样,就不多赘述

在这里插入图片描述
此时它们自己都是master

将新增的6387节点(空槽号)作为master节点加入原集群

redis-cli -a密码 --cluster add-node 自实际IP地址:6387 自己实际IP地址:6381

6387就是将要作为master新增节点

在这里插入图片描述

使用命令redis-cli -a 123456 --cluster check ip:6381 产看一下对应的集群信息,以及槽位信息

在这里插入图片描述

重新分配槽号

命令:redis-cli -a 密码 --cluster reshard IP地址:端口号

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述这里选择分配4096个槽位,主要原因是一共有16384个槽位,4台主机,16384 / 4 = 4096

再次检测集群信息,以及槽位信息

在这里插入图片描述

为什么6387是3个新的区间,以前的还是连续?
重新分配成本太高,所以之前的三台主句各自匀出来一部分, 从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387

为主机6387分配从机6388
命令:redis-cli -a 123456 --cluster add-node ip:6388 ip:6387 --cluster-slave --cluster-master-id master_id

在这里插入图片描述

在这里插入图片描述

第三次检测集群信息,以及槽位信息

在这里插入图片描述

主从缩容

从集群中将4号从节点6388删除

命令:redis-cli -a 密码 --cluster del-node ip:从机端口 从机6388节点ID

在这里插入图片描述

检测集群信息,查看从机6388是否被删除

在这里插入图片描述

将6387的槽号清空,重新分配, 本例将清出来的槽号都给6381

命令:redis-cli -a 密码 --cluster reshard ip:端口号

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

第二次检查集群信息,查看槽号是否重新分配
在这里插入图片描述
在这里插入图片描述
4096个槽位都指给6381,它变成了8192个槽位,相当于全部都给6381了,不然要输入3次

将主机6387删除

命令:redis-cli -a 密码 --cluster del-node ip:端口号 6387主机ID

在这里插入图片描述

第三次检查集群信息,查看主机6387是否被删除

在这里插入图片描述

4、集群常用操作命令和CRC16算法分析

Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽。到底CRC16是如何调用的?
看一下cluster.c源码
在这里插入图片描述

再看一下crc16.c的源码
在这里插入图片描述

先调用keyHashSlot,再调用crc16

集群是否完成才能对外提供服务

cluster-require -full coverage

在这里插入图片描述

默认是yes,现在集群架构是3主3从的redis cluster由3个master平分16384个slot,每个master的小集群负责1/3的slot,对应一部分数据。cluster-require-full-coverage:默认值 yes ,即需要集群完整性,方可对外提供服务通常情况,如果这3个小集群中,任何一个(1主1从)挂了,你这个集群对外可提供的数据只有2/3了,整个集群是不完整的, redis默认在这种情况下,是不会对外提供服务的。

如果你的诉求是,集群不完整的话也需要对外提供服务,需要将该参数设置为no,这样的话你挂了的那个小集群是不行了,但是其他的小集群
仍然可以对外提供服务。

不在同一个slot槽位下的键值无法使用mset、mget等多键操作,因为请求没有对应到相应的槽位
在这里插入图片描述

不在同一个slot槽位下的多键操作支持不好,通识占位符登场
可以通过{}来定义同一 个组的概念,使key中{}内相同内容的键值对放到一个slot槽位去

在这里插入图片描述

{ }里面的z可以换成任何标识符

cluster countkeysinslot 槽位数字编号
如果返回值为0,表示该槽位没有被占用
在这里插入图片描述

如果返回值为1,表示该槽位已经被占用
在这里插入图片描述

cluster keyslot 键名称
判断某个键的槽位
在这里插入图片描述

相关文章:

Redis集群分片

文章目录1、Redis集群的基本概念2、浅析集群算法-分片-槽位slot2.1 Redis集群的槽位slot2.2 Redis集群的分片2.3 两大优势2.4 如何进行slot槽位映射2.5 为什么redis集群的最大槽数是16384个?2.6 Redis集群不保证强一致性3、集群环境搭建3.1 主从容错切换迁移3.2 主从…...

ISP-AF相关-聚焦区域选择-清晰度评价-1(待补充)

1、镜头相关 镜头类型 变焦类型: 定焦、手动变焦、自动变焦 光圈: 固定光圈、手动光圈、自动光圈 视场角: 鱼眼镜头、超广角镜头、广角镜头、标准镜头、长焦镜头、超长焦镜头(由大至小) 光圈: 超星…...

[element-ui] el-table行添加阴影悬浮效果

问题: 在el-table每一行获得焦点与鼠标经过时,显示一个整行的阴影悬浮效果 /*其中,table-row-checkd是我自定义的焦点行添加类名,大家可以自己起名*/ .el-table tbody tr:hover,.el-table tbody tr.table-row-checked{box-shadow: 0px 3px …...

分布式存储技术(上):HDFS 与 Ceph的架构原理、特性、优缺点解析

面对企业级数据量,单机容量太小,无法存储海量的数据,这时候就需要用到多台机器存储,并统一管理分布在集群上的文件,这样就形成了分布式文件系统。HDFS是Hadoop下的分布式文件系统技术,Ceph是能处理海量非结…...

【python设计模式】20、解释器模式

哲学思想: 解释器模式(Interpreter Pattern)是一种行为型设计模式,它提供了一种方式来解释和执行特定语言的语法或表达式。该模式中,解释器通过将表达式转换为可以执行的对象来实现对表达式的解释和执行。通常&#xf…...

【PostgreSQL】通过docker的方式运行部署PostgreSQL与go操作数据库

目录 1、docker的方式运行部署PostgreSQL 2、控制台命令 3、go操作增删改查 1、docker的方式运行部署PostgreSQL docker pull postgres docker run --name learn_postgres -e POSTGRES_PASSWORDdocker_user -e POSTGRES_USERdocker_user -p 5433:5432 -d postgres进入容器&am…...

Kotlin协程序列:

1: 使用方式一 ,callback和coroutine相互转化。 import kotlinx.coroutines.* import java.lang.Exception class MyCallback {fun doSomething(callback: (String?, Exception?) -> Unit) {// 模拟异步操作GlobalScope.launch {try {delay(1000) // 延迟 1 秒…...

java获取视频时长

1、先导包 <dependency><groupId>ws.schild</groupId><artifactId>jave-all-deps</artifactId><version>2.6.0</version> </dependency>2、获取时长 Testpublic void test01() {long time 0;try {String url "http://…...

EDAS投稿系统的遇到的问题及解决办法

问题1&#xff1a; gutter: Upload failed: The gutter between columns is 0.2 inches wide (on page 1), but should be at least 0.2 inches 解决&#xff1a; 在\begin{document}前添加\columnsep 0.201 in&#xff08;0.2in也会报错&#xff0c;建议填大一点点&#xff09…...

t-learning 产品经理课程笔记

t-learning 腾讯公开课——产品经理课程 第一课 化身用户研究员&#xff0c;张小龙《产品精讲》 1-3&#xff1a;执行 4-7&#xff1a;中坚力量 7&#xff1a;核心leader 能解决问题的&#xff0c;就是好的产品经理 如何储备产品知识与素养 &#xff08;1&#xff09;了解并…...

校招,从准备开始准备(持续更新ing...)

诸神缄默不语-个人CSDN博文目录 作者现在有科研任务在身&#xff08;今天还在标数据哦&#xff09;&#xff0c;所以不能实习。 所以就是纯纯拉个表。 最近更新时间&#xff1a;2023.4.9 最早更新时间&#xff1a;2023.4.6 文章目录1. 学习资料和知识点清单1.1 机器学习1.2 深…...

Android:使用LayerDrawable动态生成四宫格头像(包含双人、三人头像)

其实用自定义View也可以实现&#xff0c;我比较懒&#xff0c;就用LayerDrawable来创建一个新的Drawable资源实现。 举例4宫格&#xff0c;9宫格原理类似&#xff0c;每个图标的位置需要用边距慢慢调成预期的效果 效果如下&#xff1a; 双人头像&#xff1a; 三人头像&#x…...

Android Jetpack 从使用到源码深耕【数据库注解Room 从实践到原理 】(三)

前面两篇文章,我们一起学习了,Room引入的背景、Room的使用方式、Room的实现原理猜想验证、Room的源码原理探索总结。 本文,我们将其中牵扯到的课外知识点 or 过程中没有说到的知识点,进行一下单独的总结。 题外话:扩展知识点总结 1. 抽象工厂的设计模式应用 在源码探索…...

中国电子学会2023年03月份青少年软件编程Scratch图形化等级考试试卷三级真题(含答案)

2023-03 Scratch三级真题 分数&#xff1a;100 题数&#xff1a;38 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1.计算“248……128”&#xff0c;用变量n表示每项&#xff0c;根据变化规律&#xff0c;变量n的赋值用下列哪个最合适&#xff1f;&am…...

分布式事务培训

MQ发生成功 MQ响应失败 断网 DIY seary 不保证隔离性&#xff0c;扣账不成功&#xff0c;钱被花了。导致回滚不成功 超时处理。 超时处理机制 防悬挂&#xff0c; try 的 try catch 导致不报错。空提交 处理链&#xff0c;inputlog万一数据库出现问题。outlog 最终保证回滚。映…...

关键词采集工具可以帮助我们做那些方面的工作

针对搜索引擎的关键词采集工具可以帮助我们做那些方面的工作&#xff0c;至少从10个工作场景说明&#xff0c;并列举详细的使用场景 Msray-plus&#xff0c;是一款企业级综合性爬虫/采集软件。 支持亿级数据存储、导入、重复判断等。无需使用复杂的命令&#xff0c;提供本地W…...

2023年5月PMP难考吗?

PMP考试难不难&#xff0c;还是因人而异的&#xff0c;对小白而言&#xff0c;肯定是难的&#xff0c;对项目管理老人而言&#xff0c;难度肯定是没那么高。 难点主要是非常多而难理解的知识点&#xff0c;以及答题时的知识点提取。经过系统的学习&#xff0c;分解知识点&…...

定语从句的省略

1. 关系代词的省略&#xff08;即that which之类的&#xff09; 条件&#xff1a;首先限制定语从句&#xff08;即没有逗号的&#xff09; 先行词在从句中作宾语成分 两个条件缺一不可&#xff0c;先行词中作主语成分是不可以的。&#xff08;这就是形容词短语作定语后置和定…...

简易小工具实现批量打开多个网页

最近有个需求&#xff0c;希望一次性可以打开多个网页&#xff0c;网址自由指定&#xff0c;这个需求的实现非常简单&#xff0c;使用基本的c代码调用system函数即可&#xff0c;都不需要MFC相关的东西。 但是我实测一些工具后发现一个问题&#xff0c;当打开超过大约3个网址的…...

swiper 点击事件

点击swiper 获取当前下标 两种模式 "swiper": "^5.4.5", "vue-awesome-swiper": "^3.1.3",swiperOption: {autoplay: { delay: 3000 },loop: true, //循环slidesPerView: auto,direction: "vertical",disableOnInteraction:…...

旅游心得Traveling Experience

前言 加油 原文 旅游心得常用会话 ❶ Share photos of the trip with friends. 与朋友分享旅游的照片。 ❷ We’ll go to the Great Wall, if you prefer. 你如果愿意的话,我们去长城。 ❸ Would you go to the church or the synagogue or the mosque? 你会去教堂,犹太…...

【 SpringBoot ⽇志⽂件 】

文章目录一、⽇志的作用二、认识⽇志三、⾃定义⽇志打印3.1 在程序中得到⽇志对象3.2 使⽤⽇志对象打印⽇志3.3 ⽇志格式说明四、⽇志级别4.1 ⽇志级别的作用4.2 ⽇志级别的分类与使⽤4.2.1 ⽇志级别的分类4.2.2 ⽇志使⽤4.2.2.1 配置全局日志级别4.2.2.2 配置局部文件夹的日志…...

ThinkPHP路由不转换的原因及解决方法

随着互联网的发展&#xff0c;网站开发技术日新月异。而ThinkPHP作为一款流行的PHP开发框架之一&#xff0c;也在不断地吸纳更多的开发者来使用。然而&#xff0c;有时候我们在使用过程中会遇到一些问题&#xff0c;比如ThinkPHP路由不转换的问题。本文将详细介绍这个问题以及解…...

【案例教程】基于RWEQ模型的土壤风蚀模数估算及其变化归因分析实践技术

土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一&#xff0c;土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的首要过程。中国风蚀荒漠化面积达160.74104km2&#xff0c;占国土总面积的16.7%&#xff0c;严重影响这些地区的资源开发和社会经…...

Twitter推荐算法总架构和算法说明

Twitter推荐算法总架构&#xff1a; 这个推荐架构的作用是生成在用户首页上显示的推文列表 步骤&#xff1a; 1、从不同的推荐来源中获取最好的推文&#xff0c;这个过程被称为候选来源。 2、使用机器学习模型对每条推文进行排名。 3、应用启发式方法和过滤器&#xff0c;例如…...

1.C语言题目---指针类(基础)

1. 小端,低地址存低字节,高地址存高字节 大端,低地址存高字节,高地址存低字节 人类读写数据习惯是大端字节序 比如说数字12345678在寄存器大端存储顺序如下: 在寄存器小端存储顺序如下: 假设&#xff0c;a变量的地址为0x64&#xff0c;则a变量在内存中的模型为&#xff1a; 0…...

【算法与数据结构】关于排序的问题思考

文章目录引言不断的插入值&#xff0c;并保证序列是递增的。Python中sort()和sorted()的区别是啥&#xff1f;sorted 函数如何使用&#xff1f;问题&#xff1a; 如何返回排序之后的索引问题&#xff1a;排序的稳定性问题&#xff0c;寻找第K大的元素的算法。引出一个算法题&am…...

行为型模式-命令模式

行为型模式-命令模式命令模式&#xff08;Command&#xff09;解决命令执行问题描述适用环境优点&#xff1a;缺点&#xff1a;违反原则&#xff1a;代码实现命令模式&#xff08;Command&#xff09; 解决命令执行问题 描述 将一个请求封装为一个对象&#xff0c;并定义该对…...

SHELL综合练习1

文章目录1、编写函数&#xff0c;实现打印绿色OK和红色FAILED 判断是否有参数&#xff0c;存在为Ok&#xff0c;不存在为FAILED2、 编写函数&#xff0c;实现判断是否无位置参数&#xff0c;如无参数&#xff0c;提示错误3、编写函数实现两个数字做为参数&#xff0c;返回最大值…...

ROS开发之如何使用发布者、订阅者和话题消息?

文章目录0、引言1、创建发布者&#xff08;velocity发布者 →geometry话题消息→turtlesim订阅者&#xff09;2、创建订阅者&#xff08;turtlesim发布者→turtlesim话题消息→pose订阅者&#xff09;3、自定义话题消息4、使用自定义话题消息&#xff08;person发布者→自定义话…...