海量数据如何“安家”?一文读懂哈希、范围和一致性哈希三大分片策略

C#分片策略实战:3大核心策略+5步实现,如何选最佳方案? 摘要: 本文探讨C#实现数据分片的三大核心策略:哈希分片(简单均匀但迁移成本高)、一致性哈希(动态扩展但实现复杂)和动态分片(灵活可控需手动管理)。通过代码示例对比各方案优缺点,并给出5步落地指南,帮助开发者根据业务场景(数据量、分片稳定性等)选择最佳分片方案。文末总结指出:哈希分片适合固定场景,一致性哈希利于动态扩展,动态分片则适用于不可预测的海量数据。 阅读详情

将单机问题转化为分布式解决方案时,首要任务是对问题进行分解,使得集群中的每台机器负责处理原问题的一个子集。无论是计算任务还是存储任务,其操作对象都是数据。因此,如何将海量数据有效地分解并分配到集群的不同节点上,即数据分布(也常称为数据分片,Data Partitioning/Sharding),是构建分布式系统的基础。

哈希分布
哈希分布(Hash-based Partition)是通过哈希函数(如MD5、SHA-1或简单取模)将数据的键(Key)映射到固定范围的哈希值,再根据哈希值将数据分配到不同的节点。
哈希分布(Hash-based Partition)通过一个确定的哈希函数(如MurmurHash、CRC32,或者简单的取模运算;MD5、SHA-1等加密哈希也可用于需要强随机性的场景,但通常计算开销较大)作用于数据的某个键(Key),将键映射到一个固定范围的哈希值。然后,根据哈希值(例如,hash(key) % num_nodes)将数据分配到对应的节点。
良好的哈希函数可以将数据尽可能均匀地散列到各个节点,避免数据倾斜,从而实现负载均衡。然而,当集群中的节点数量发生变化(增减节点)时,如果采用简单的取模方式(% num_nodes),绝大多数数据的哈希映射关系都会改变,导致大规模的数据迁移(如节点从10个扩容到11个,约90%的数据需要迁移)。

在这里插入图片描述

数据范围分布
数据范围分布(Range-based Partition)根据数据的键值(如时间戳、自增ID、字母顺序等具有序关系的属性)将其划分为连续的区间,每个节点负责存储一个或多个这样的数据区间。例如,一个订单表可以按月份范围(2023-01 至 2023-03,2023-04 至 2023-06等)划分,并将不同月份的数据存储在不同节点上。
由于数据在物理上按键顺序存储,范围查询(如查询某个时间段内的所有订单)非常高效,数据局部性好。然而,如果某些键值范围的数据量远大于其他范围,或者访问频率远高于其他范围(例如,当前月份的订单总是被频繁访问),则可能导致对应节点的负载过高,形成热点。

在这里插入图片描述

一致性哈希分布
一致性哈希(Consistent Hashing Partition)是为了解决传统哈希分布在节点数量动态变化时导致大规模数据迁移问题而提出的优化算法。它将所有节点和数据的键都通过同一个哈希函数映射到一个逻辑上的环形哈希空间(例如 0 到 232−1)。数据键被分配给在环上沿顺时针方向寻找到的第一个节点。
Ketama Hash 是经典实现之一。Rendezvous Hashing、Jump Consistent Hash、Maglev Hash 等也是在不同场景下具有特定优势的一致性哈希变种。
Ketama Hash又称割环法。在Ketama Hash中,将节点通过哈希方式,映射到一个范围是[0,2^32]的环上,同理,把数据也通过哈希方式映射到环上,然后按顺时针方向查找第一个哈希值大于等于数据的哈希值的节点,该节点即为数据所分配到的节点。而更好点的做法,可以为每个物理节点分配若干个虚拟节点,然后把虚拟节点映射到哈希环,分配给每个物理节点虚拟节点数量对应每个物理节点的权重。
如下图所示,数据K1映射到了节点2,数据K2映射到节点3。

在这里插入图片描述

1)扩容:对于割环法的扩容,只需在环上增加一组扩容节点生成的虚拟节点;
2)缩容:同样的,缩容时只需拿掉缩容节点对应的所有虚拟节点;
3)故障容灾:割环法的故障容灾与缩容情况一样,节点故障时只需将故障节点对应的所有虚拟节点从环上去掉。

在这里插入图片描述

如上图所示,当节点2故障时,将节点2对应的2个虚拟节点去掉,而原本映射到节点2的对象K1和K2分别映射到了节点1和节点4。

未完待续

很高兴与你相遇!如果你喜欢本文内容,记得关注哦!!!

数据结构与算法22丨哈希算法(下):哈希算法在分布式系统中有哪些应用? 上一节,我讲了哈希算法的四个应用,它们分别是:安全加密、数据校验、唯一标识、散列函数。。你可能已经发现,这三个应用都跟分布式系统有关。没错,今天我就带你看下,。 阅读详情

相关推荐

Java 分布式系统:一致性哈希算法的原理与应用

一致性哈希算法是一种高效的分布式算法,它通过将对象和节点映射到哈希环上,解决了分布式系统中数据分布和节点管理的问题。尽管它有一些局限性,但在许多实际场景中,它仍然是一个非常有用的工具。通过合理的实现和优化,一致性哈希可以帮助我们构建更加稳定和高效的分布式系统。

shrgegrb的博客 1139

【数据结构】哈希(Hash)

数据结构:哈希函数

秋之回忆Alex的博客 9215

在ros里给机械臂加上夹爪和底盘后,控制真实机械臂

使用ur3_bringup 可以连接真实机械臂 使用官方的ur3_moveit_planning_execution.launch 可以对机械臂 moveit规划。 但是只有机械臂,没有夹爪。 官方如图: 我把原来的ur3_moveit_config 复制出来,修改 然后把ur3.xacro 等模型文件复制出来修改,修改完之后,有了夹爪,有了底盘。 规划组什么的使用moveit setup assistant 配置过了。 在rviz中可以笛卡尔空间规划了。 ...

超级菜 2716

mysql实现hash分表

mysql作为站点后端的重要数据落地组成部分,可谓是运用相当之广泛。在web应用中,往往庞大的数据会最终落地到mysql中,当一张mysql单表记录了上10亿的记录时,性能往往不会很理想,于是我们往往会将一张单表拆分成多张相同的分表。今天我们主要来讲如何合理的进行分表。 1、对一个字段进行分表: 这种分表方式,是我在工作中直接应用到的一种方式: 举一个简单的例子: 比如电商网站,需要记录用

dengjiexian123的专栏 2万+

Hadoop生态系统-新手快速入门(含HDFS、HBase系统架构)

Hadoop简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。 Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量...

Hadoop环境搭建教程 472

大整数因数分解工具——yafu

可以将大整数放在一个新建文件中——data.txt,最后面一定要换行,不然会出现eof;done processing batchfile,运行命令。2.点击设置——系统——系统信息——高级系统设置——环境变量——点击PATH(上下都可以)——新建 添加yafu-x64.exe 所在路径——点击确定。,如果整数数过长,会出现错误mismatched parens;1.找到yafu-x64.exe 所在的文件路径。如果出现以下图像,说明配置成功。3.打开cmd,输入。

l2ohvef的博客 6156

哈希算法和哈希学习分类

哈希 1.先来了解一下Hash的基本思路: 设要存储对象的个数为num, 那么我们就用len个内存单元来存储它们(len>=num); 以每个对象ki的关键字为自变量,用一个函数h(ki)来映射出ki的内存地址,也就是ki的下标,将ki对象的元素内容全部存入这个地址中就行了。这个就是Hash的基本思路。 Hash为什么这么想呢?换言之,为什么要用一个函数来映射出它们的地址单元呢? Th

weixin_40396948的博客 7336

解密 vn.py 源码:从事件驱动到模块化设计的实战解析

本文深入解析vn.py源码,重点剖析其事件驱动机制与模块化设计。通过事件引擎、处理器字典等核心组件分析,展示如何实现低耦合高内聚的交易系统架构,并结合实战案例说明模块化设计带来的开发效率提升。文章还详细解读了Gateway抽象层、核心数据结构及设计模式应用,为量化交易开发者提供源码级实践指南。

weixin_27427619的博客 250

哈希分区和顺序分区_SQL Server中的哈希分区

哈希分区和顺序分区 In SQL Server, when talking about table partitions, basically, SQL Server doesn’t directly support hash partitions. It has an own logically built function using persisted computed columns...

culuo4781的博客 2231

freeswitch之呼叫中心acd模块开发

一、定义: ACD(Automatic Call Distributor) 自动呼叫分配,也叫智能选择座席。它是呼叫中心整个前台接入系统逻辑功能的描述:把接入的呼叫转接到正确的座席员桌前。ACD是现代呼叫中心有别于一般的热线电话系统和自动应答系统的重要标志,其性能的优劣直接影响到呼叫中心的效率和顾客的满意度。 二、ACD包含的功能点: 1 、程控交换功能 ACD在本质上也是交换机的一种类型,必须具有程控交换最基本的话务交换功能。 2 、排队功能 ACD必须具有话务排队的功能,所谓排队是指在内线都

飞鸟的博客 1870

C#.NET斗地主服务端核心架构与高性能实现

斗地主作为典型的实时对战棋牌逻辑,本质是状态驱动的分布式协同问题。其技术内核涵盖有限状态机建模、低延迟网络同步、无GC内存操作与轻量级AI决策等关键能力。在.NET平台下,借助Span<T>、ImmutableArray、命令/事件总线与内存池等特性,可构建出高吞吐(200+ QPS)、低延迟(<150ms)、强一致的可落地服务端。本文聚焦C#.NET生态中斗地主核心模块的设计取舍与压测验证,深入解析状态机驱动、CardSet结构体优化、Kestrel中间件锁、规则+概率混合AI等实战方案,为实时对战类业务

weixin_29726381的博客 345

哈希分片总结

主要参考: 《大数据日知录》 https://zhuanlan.zhihu.com/p/34985026 什么是哈希分片 后台随着数据规约的越来越大,单机明显无法存储着庞大的数据量,只能依靠大规模集群在对数据进行存储和处理,所以系统的可扩展性也成为了很重要的一个点。 目前主流的大数据存储于计算系统通常采用横向扩展的方式支持系统的可扩展性,即通过增加机器数量来获得水平扩展能力。与此对应,对于待存...

许佳佳的博客 4155

YOLO26创新改进 | 全网独家创新篇、小目标检测专属 | AAAI 2025 | 引入HS-FPN中的HFP和SDP创新点,从频域增强小目标特征,淘汰FPN进行升级,助力YOLO26有效涨点

本文提出HS-FPN特征金字塔网络,通过高频感知模块(HFP)和空间依赖感知模块(SDP)优化YOLO26模型。HFP利用高通滤波器增强小目标的高频特征,SDP捕获相邻像素的空间依赖关系。在AI-TOD等小目标检测数据集上,HS-FPN相比传统FPN显著提升性能。文章详细介绍了HFP和SDP的模块结构、核心代码实现,以及如何在YOLO26中集成这两个模块的配置方法,提供了多个版本的yaml文件配置方案。实验结果表明该方法能有效改善微小目标检测效果。

Ai缝合怪、助力小伙伴高效发论文 207

必学算法——哈希算法

哈希算法是必须掌握的一种基础算法,在一些比较出名的竞赛acm、蓝桥杯,并且在一些公司面试题中都可能会出现,而且作为简单题我们必须要拿下,所以我们要引起重视,下面让我们来深入了解哈希算法。哈希算法,也称为散列算法,是一种数学函数或算法,它能够将任意长度的数据(称为“消息”)转换为固定长度的字符串(称为“哈希值”或简称“哈希”)。学习算法是一个很艰难,漫长的过程,我们要克服一切困难,学习算法本就是由易到难,我相信通过我们坚持不懈的努力一定能理解并熟练掌握其中细节,加油,我相信你一定能行。

ycs66的博客 5287

C#与天文观测:Celestia模拟星空的奇幻之旅

Celestia就像一艘穿梭在星海中的小飞船,带领我们遨游宇宙。C#则是这艘飞船的智能导航系统,用代码指挥它飞向任何我们向往的星球或星系。首先,下载并安装Celestia,熟悉其基本操作和功能。创建一个星空目标列表,包括不同的恒星、行星和星系。// 示例:定义观察目标列表new SpaceObject("太阳"),new SpaceObject("月球"),new SpaceObject("火星")

java专栏 1456

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

一致性哈希算法详解

在当今的互联网时代,随着大数据和分布式系统的迅猛发展,如何高效地存储和检索海量数据成为了一个亟待解决的关键问题。传统的哈希算法在面对节点动态增删时,往往会导致大量的数据重新分配,进而影响系统的性能和可用性。为了解决这一难题,一致性哈希(Consistent Hashing)算法应运而生。一致性哈希(Consistent Hashing)是一种用于分布式系统中的哈希算法,旨在解决因节点增删导致的数据重新分配问题。

hello.reader 1786

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Python Sharding 数据库分片策略解析

数据库分片是一种水平扩展的技术,它将数据分散到多个数据库实例中,每个实例称为一个分片(Shard)。通过这种方式,可以有效减轻单一数据库的压力,提高系统的性能和可用性。在 Python 应用中,分片策略的选择直接影响到系统的效率和可维护性。数据库分片是应对大数据量和高并发场景的重要手段。在 Python 应用中,合理选择分片策略对于提升系统性能至关重要。本文介绍了哈希分片、范围分片和一致性哈希三种常见策略,并分析了各自的优缺点及适用场景。希望读者能够根据自身需求灵活运用这些技术,构建高效稳定的分布式系统。

2501_90748733的博客 1561

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

如何利用xxHash构建高性能分布式系统:一致性哈希与数据分片终极指南

在分布式系统设计中,数据存储与检索的效率直接决定了系统的整体性能。xxHash作为一款**超高速非加密哈希算法**,凭借其毫秒级处理速度和低资源占用特性,已成为构建高性能分布式架构的理想选择。本文将系统讲解如何基于xxHash实现一致性哈希与数据分片策略,帮助开发者解决分布式环境下的数据分布不均、节点动态扩展等核心难题。 ## 一、为什么选择xxHash?解密速度与稳定性的双重优势 xxHas

gitblog_00090的博客 936

图解什么是一致性哈希算法

1. 写在前面周末就像太阳,总会到来,也总会离开。此刻,没错,是周六呀!还是双休那种!昨晚在B站看了几个长视频,导致2点才睡觉,早上一觉醒来已经10点了。在这里温馨提示各位盆友们,虽然我...

weixin_41385912的博客 537
上一篇: “卧槽,系统又崩了!”——别慌,这也许是你看过最通俗易懂的分布式入门
下一篇: “你还活着吗?” “我没死,只是网卡了!”——来自分布式世界的“生死契约”
milanyangbo
博客等级 码龄11年 199粉丝 67原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

milanyangbo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值