Redis系列之——深入了解Redis的String,源码层级+极易理解图片解析

Redis系列之——深入了解Redis的String,源码层级+极易理解图片解析! 在上一篇文章中,我和大家介绍了Redis的前世今生,,这一篇就和大家一起揭秘Redis神秘的面纱,第一个我们就来聊一聊Redis数据类型中的。 阅读详情

前言

在上一篇文章中,我和大家介绍了Redis的前世今生,Redis的诞生就是为了解决mysql中IO性能的瓶颈,这一篇就和大家一起揭秘Redis神秘的面纱,第一个我们就来聊一聊Redis数据类型中的String!

Redis的数据结构

Redis最常用的数据类型有五种

  • String: 字符串
  • Hash: 散列
  • List: 列表
  • Set: 集合
  • Sorted Set: 有序集合

五种其实是Redis键值对中值存储的数据类型,而他们的底层数据结构一共有6种:分别是

  • 简单动态字符串
  • 双向链表
  • 压缩列表
  • 哈希表
  • 跳表
  • 整数数组

数据类型和数据结构的对应关系如下图:

这张图会在未来几篇文章中反复出现,帮大家彻底了解Redis的基础类型。

今天我们就来聊一聊其中的string

Redis是用C写的,那为什么不用C语言的String?

众所周知,Redis是用C语言写的,那Redis为什么没有使用C原生的字符串,而是自己创建了一个简单动态字符串?(SDS simple dynamic string)

  • C语言的字符串底层是用字符数组来实现的,在一片连续的空间中依次存放字符,为了判断字符的结束,他会在最后以'\0'作为识别,这样就会带来以下问题

    1. 无法存放任意的字符,至少'\0'是不可以的,这就会导致一些如图片,音频等出现了'\0'就会出现问题。
    2. 对字符串进行追加等操作的时候,必须遍历到'\0'才可以操作,会导致效率比较低,复杂度为o(n)
  • C语言的字符串是不记录字符串长度的,一旦我们调用了拼接函数等,而没有提前计算好内存,就会产生缓冲区溢出的情况,所以为了不出问题,会进行内存重分配,而这又多出了内存重分配的性能损耗。

那么,Redis是怎么处理这些问题的呢?

简单动态字符串(Redis5.0版本)

Redis中的字符串数据是通过简单动态字符串(以下简称SDS)来存储数据的。

SDS到底是什么?

我们先来看看SDS的结构长什么样

  • len:表示buf的已用长度。(sdshdr8中占1个字节)
  • alloc:表示分配给buf的总长度,不包括结构体和'\0'结束字符。(sdshdr8中占1个字节)
  • flags: SDS类型。(sdshdr8中占一个字节)
  • buf:字节数组,保存实际数据。为了表示字节数组的结束,Redis 会自动在数组最后加一个“\0”,这就会额外占用 1 个字节的开销。(nycdf--> 你也才掉发是我在这里写的示例,代表存储的某个数据)

你丫才掉发小课堂--详解SDS类型

SDS 结构中的字段 flags,表示的是SDS的类型。在Redis中SDS一共设计了5种类型,分别是

  • sdshdr5(未使用)
  • sdshdr8
  • sdshdr16
  • sdshdr32
  • sdshdr64

这5种类型的主要区别就在于,它们数据结构中的len和alloc,这两个字段占据的大小不同,也就是这个结构体能存储的长度不同。下面他们是结构体的源码:

从源码我们可以看出来,其实最大的不同就是len和alloc所代表的字节数不同,那么比如sdshdr8中这2个字段的类型uint8_t,也就是这个类型结构最大存储的字符长度为256(2的8次方),其他的以此类推。

这样的设计目的:Redis是基于内存的,而内存永远都是珍贵的资源,每一个字节都很重要,所以针对不同大小的字符串使用不同的结构,也是为了节省内存资源。

在SDS中,除了上面解释过的flags,对比于C传统的char[],SDS新增了2个参数,实际占用长度len 和总分配长度alloc。

SDS解决了什么问题呢?

1. 获取字符串长度的复杂度问题

上面我们说过,c语言遍历一下字符串的复杂度是o(n)。

对于SDS来说,我们有了长度的参数,那么我们的复杂度就是o(1),这样在进行拼接等操作的时候不需要再次遍历了。

2. 存储二进制数据

C字符串不能存储二进制数据的原因是只能根据'\0'来判断数据是否结束,不能保证其完整性,但因为SDS的len属性,无论你数据里有多少'\0'都没关系,我是根据 len 属性值来判断数据长度的,必定是完整的,所以SDS可以安全地存储二进制数据,这样图片音频等二进制数据也可以存储。

你丫才掉发小课堂

Q:SDS你都有len了,那为啥还要跟C字符串一样在字符串后面加'\0',是不是多此一举了?

A:SDS如果保持和C字符串一样的特性,就不用专门编写多余的函数了,在一定的情况下可以直接用C语言的函数,避免了不必要的重写。

3. 分配内存空间问题

上面还在存在一个问题是在使用拼接等操作的时候C语言是需要重分配空间的,而这个又是非常的消耗资源。SDS提供的2个特性就是空间预分配 和 惰性空间释放

空间预分配

空间预分配源码

在真正执行拼接等操作之前,会先计算下空间是否满足

  1. 如果计算后的SDS的长度(源码中的newLen)小于1MB,那么就会分配和len属性同样大的未使用空间,相当于将原数组长度乘以二。

  1. 如果计算后的SDS的长度(源码中的newLen)大于或等于1MB,那么就会分配固定的1MB未使用空间。

所以当有N次拼接操作时候,一定需要N次的内存重分配操作,现在最多只需要N次。

比如你第一次拼接后,剩余的长度(alloc - len)就大于后续要拼接的字符串长度之和了,那其实就只有1次内存重分配操作,就可以进行至少2次拼接操作,所以说最多N次,这也就可以省下很多分配空间的消耗。

惰性空间释放

当有缩短SDS字符串操作时,程序并不立即把空闲出来的字节释放掉,而是留给到惰性删除策略等机制释放。

具体的表现就是:

在做删除操作的时候,当删掉N个字符后,alloc-len(也就是剩余空间)就增加N,换个说法,就是你删除的字符并没有立即被系统回收,这样当你短时间内再次拼接的时候,就不会申请空间分配了。

只有到了对应策略或者手动去删除的时候才会执行以下的代码:

代码的逻辑就是删除多余的空间直到没有浪费为止。

有了SDS,就万事大吉了么?

前面我们聊完了SDS,已经大概的知道了SDS是什么样的,解决了什么问题,这里给大家提出一些更深层的问题:

  1. 如果我的string是数字,Redis也按照字符串存储么?
  2. string在Redis中就是只有SDS就可以落地了么,有没有别的结构支撑?
  3. SDS最大支持存储长度为2的64次方的数组,这些超长的字符串他们是怎么存储的?

初识RedisObject

在我们真实使用Redis中string的时候,除了SDS的存储空间,还存在一个Redis本身的结构体,也就是RedisObject。

RedisObject存储空间

以上是RedisObject源码,

  • type:redisObject的数据类型,4个bits
  • encoding:redisObject的编码类型,4个bits
  • lru:LRU_BITS:redisObject的LRU时间,LRU_BITS为24个bits
  • refcount:redisObject的引用计数,4个字节
  • *ptr:指向值的指针,8个字节

为了形象的展示占据的大小:

RedisObject和String

这里暂时不对RedisObject展开讲,我们来看看当RedisObject和SDS在一起的时候大概是个什么样子?

上图表示的就是普通情况下RedisObject和SDS的关系。

作为Redis最常用的结构之一,针对String也做了很多的优化

1. 数字类型的字符串

对于数字类型的字符串,Redis在RedisObjec中的指针就直接赋值为整数数据了,这么指针的开销就省去了。

2. embstr编码方式(embed:嵌入式)

在保存的是字符串数据,如果字符串小于等于44字节时(为什么是44呢?读到这里可以思考一下),Redis就会将RedisObjec和SDS构建成一块连续的内存区域,既可以提升查询的速度(少了一次指针的跳转),也可以防止内存碎片的产生。

我们先来看下这里判断的源码:

  • 当字节数小于44,调用createEmbeddedStringObject
  • 当字节数大于44,调用createRawStringObject

这里我们来看下createEmbeddedStringObject的部分源码

这里做的事情核心

  1. 先分配一段连续的内存空间(RedisObject+SDS+1的长度,这里的1是为了字符串最后的`'\0'),并创建RedisObject和SDS的机构。
  2. 将RedisObject的ptr指针指向字符数组的开始。(细节!!!!)
  3. 拷贝字符串到SDS的buf[]中。

这个时候内存块包含如下几部分:

  • 16个字节的robj结构。
  • 3个字节的sdshdr8头。
  • 最多44个字节的sds字符数组。
  • 1个'\0'结束符。

3. raw编码模式

在保存的是字符串数据,字符串大于44字节时,Redis就不像embstr编码方式一样把RedisObject和SDS存放在一起,这时RedisObject中的*ptr就会发挥真正的作用,Redis在内存中重新分配一块空间给SDS,并用*ptr指向这个SDS。

这里我们来看下createRawStringObject的部分源码

这里就比较简单了,一共做了这2件事:

  1. 先使用sdsnewlen返回SDS结构的指针
  2. 将SDS指针赋值给RedisObject中的指针

最后再给大家把所有的编码格式放一起汇总一下:👇

数据库之Redis运维手册(私人整理) 1、redis配置文件 #cat 8000.conf daemonize no #[yes/no]默认值no,该参数用于定制redis服务是否以守护模式运行。 pidfile /var/run/redis.pid #默认值/var/run/redis.pid,指定redis服务的进程号文件路径,以守护模式运行时需要配置本参数; port 8000 #默认值6379,指定redis服务... 阅读详情

相关推荐

LLVM实战:如何用Clang+LLVM打造你的第一个C++编译器(附完整配置步骤)

本文详细介绍了如何使用Clang+LLVM构建C++编译器的完整配置步骤,从环境准备到编译流程剖析,再到调试与优化技巧。通过实战指南,帮助开发者深入理解LLVM编译器框架的工作原理,并掌握交叉编译与性能分析等高级功能。

sprite的博客 748

Redis 6.2 redis创建一个字符串对象是如何选择合适的编码方式(源码)

通过Redis 6.2 key的创建SDS(源码)知道String在redis中是有多种编码方式存储的,但是对一段字符串如何进行选择编码方式就不清楚了,下面就是redis在保存数据时,字符串编码方式如何选择的源码 文章目录当键值对的value是字符串时,入口方法选择String类型的编码方式createRawStringObject(OBJ_ENCODING_RAW 编码方式)createEmbeddedStringObject(OBJ_ENCODING_EMBSTR 编码方式) 当键值对的value是.

胖墩的IT博客 1196

深度学习笔记(3)——kernel(内核)与filter(滤波器)

本文仅仅简单介绍了kernel和filter的概念,介绍了确定filter和kernel个数的方法。

cs111211的博客 7142

Redis源码-String:Redis String命令、Redis String存储原理、Redis String三种编码类型、Redis字符串SDS源码解析、Redis String应用场景

编码转换在Redis写入数据时完成,且转换过程不可逆,只能从小内存编码向大内存编码转换(不包括重新set),重新set虽然在值上是修改或插入,但在Redis看来是重新赋值,这里的编码转换指的修改比如说拼接字符串、自增这种,非set的改值操作。Redis的key是字符类型,即String,最大可以用得到是512M,那么它的value字符类型,也是String,最大也是512M。中文标点占三个字节,英文标点占一个字节。1,ASCII码:一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。.

郝开的博客 1820

【校园网代理连接问题】已解决,“该设备或资源(Web 代理)未设置为接受端口“7890”上的连接“

我遇到这个问题很多次。每次都是vpn的问题,不止通俗意义上的梯子(clash之类的),还包括校园网vpn。点击“ 拨号和虚拟专用网络设置”中的“设置”, 关闭代理服务器。在打开vpn后或者关闭vpn后无法浏览网页,网页诊断显示“关闭“手动设置代理”中的“使用代理服务器”,关闭对应的本地代理即可。

聆雨。 1万+

OV5640调试大坑,关于binning、RES分辨率与EV曝光

OV5640在使用binning模式时,必须考虑使用场景,分辨率下降叠加动态范围压缩,会使目标对象细节在高光环境下大量丢失,2x2的binning模式,分辨率会远低于感光面积的1/4。

chongyun_的专栏 1829

Redis之object源码阅读

在这片博客中,我们将对object.c这个文件的其中一些方法进行阅读,大部分代码都是类似的: createObject:创建一个新对象 robj *createObject(int type, void *ptr) { robj *o = zmalloc(sizeof(*o)); o->type = type; o->encoding = REDIS_ENC...

m0_37343985的博客 228

毫米波雷达dd-mimo中发射天线辐射方向图变化

本文详细介绍了dd-mimo的相位调制原理,以及分离天线的办法,最后演示了在dd-mimo中因为相位调制带来的辐射方向图的变化。

weixin_44555637的博客 1171

redis五大基本数据类型之(源码分析)

在redis6当中这个数据类型的编码主要是而在redis7当中的物理编码对应是。

qq_56999918的博客 935

CarSim转向控制对比指南:开环扭矩控制vs转角控制(附Simulink连接示例)

本文深入对比了CarSim中车轮转角控制与开环扭矩控制的核心原理与适用场景。开环扭矩控制能激活完整的转向系统动力学,更适用于EPS控制策略开发与驾驶员在环仿真等对真实性要求高的场景。文章提供了详细的Simulink接口配置步骤与连接示例,为车辆动力学仿真工程师提供了清晰的决策与实操指南。

weixin_29199873的博客 480

解决mmdet3d安装中因PyTorch高版本引发的THC.h缺失问题

本文详细分析了在安装mmdet3d时,因PyTorch版本过高导致THC.h头文件缺失的常见报错问题。文章指出该错误的本质是PyTorch 1.7+版本废弃了旧API,与老版本C++扩展代码不兼容。提供了两种核心解决方案:一是降级PyTorch至1.6及以下版本;二是修改源码,将THC.h引用替换为ATen/cuda等新头文件,并给出了具体的代码修改示例和排查技巧。

weixin_29085151的博客 383

Redis String 类型深度解析与最佳实践

在当今的互联网时代,数据存储和快速访问是许多应用的核心需求。想象一个在线购物平台,用户在浏览商品时,系统需要实时展示商品信息,包括价格、库存等。这些信息需要频繁地被读取和更新,如果使用传统的数据库系统,可能会因为频繁的读写操作导致性能瓶颈。这时,Redis作为一种高性能的键值存储系统,就成为了解决这一问题的理想选择。Redis中的String类型数据结构,正是实现这类快速读写操作的关键。

我是Java程序员廖志伟,感谢朋友们的支持!不定期贡献一篇高品质、过万文字、图文并茂且附有视频解说、满载代码示例注释的良心之作,坚决杜绝粗制乱造。 690

【Hermes Agent】2026 Hermes Agent 最新入门级实战指南:从原理、部署、模型配置到落地 Demo

当下 Vibe Coding、AI 自动化时代,单纯对话大模型已经没有竞争力,

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 248

Redis中String数据类型原理实现

微信公众号:Java患者专注Java领域技术分享String 数据模型首先Redis是KV数据结构,跟JDK中的Map是一样的,Redis是通过hashtable实现的,我们把这个叫做外...

ZeJava的博客 1045

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

jre9下载 jdk9

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

redis底层数据结构 -String

redis包含5种常用数据结构 String 、List、Hash、Set 、Zset String 字符串不同的外在形式 以set为例 redis其实可以理解为 K-V数据库,因此对每个键值对都会有一个 dictEntry,里面存储了指向 Key 和 Value 的指针;next 指向下一个 dictEntry,与本 Key-Value 无关 key 可以看出 key不是直接存的字符串,而是一个SDS结构 value value既然不是存的String,也不...

liang只的博客 3860

深度学习工具包 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")

对redis的新认知 九种数据类型

90%的人知道Redis 5种最基本的数据结构; 只有不到10%的人知道8种基本数据结构,5种基本+bitmap+GeoHash+HyperLogLog; 只有不到5%的人知道9种基本数据结构,5.0最新版本数据结构Streams; 只有不到1%的人掌握了所有9种基本数据结构以及8种内部编码; 掌握这篇文章的知识点,让你成为面试官眼中Redis方面最靓的仔! 说明:本文基于Redis-3.2.11...

qq_40306091的博客 3301

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Redis中的发布订阅和事务

本文是Redis系列的第七篇文章,了解前面的文章有助于更好的理解本文:1.Linux上安装Redis2.Redis中的五种数据类型简介3.Redis字符串(STRING)介绍4.Redis字符串(STRING)中BIT相关命令5.Redis列表与集合6.Redis散列与有序集合发布订阅redis的发布订阅系统有点类似于我们生活中的电台,电台可以在某一个频率上发送广播,而我们可以接收任何一个频率的广播,Android中的broadcast也和这类似。订阅消息的方式如下:127.0.0.1:6379> SUBS

2401_84049282的博客 1044

redis篇(一):redis基本数据结构

redis篇(一):redis基本数据结构redis基本数据结构StringHashListSetZsetBitmapsHyperloglogsStreams redis 后续源码文件名称统一通过()表示,redis底层是C语言,因此.h、.c文件可认为是源码文件 源码版本 redis-6.0.5 redis全称:REmote DIctionary Service 译为远程字典服务 每个KV键值对都存储在dictEntry(dict.h)里面,redis底层是哈希表(hashTable),结构体现在

林伟杰的博客 654

Redis实现源码-字符串基础数据类型分析

Redis并没有直接使用C语言中的字符串类型,而是自己设计了一种数据结构,在Redis中,C语言中的字符串只使用在一些字符串值不会发生修改的地方,比如打印日志。它为什么要这样做?这样做的好处是什么呢?让我们先来了解一下这种被称为Simple dynamic string(SDS)简单动态字符的结构。 ...

qq_40280705的博客 329

Redis系列笔记之 —— 键

单位秒。 设置 key 的过期时间以毫秒计 PEXPIRE key milliseconds 和 EXPIRE 类似 EXPIREAT key timestamp EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置过期时间。 不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。 和 EXPIRE 类似 PEXPIREAT key milliseconds-timestamp 设置 key 过期时间的时间戳(unix timest

KG_181的博客 350

redis源码--动态字符串

sds要点总结: 1.sds定义为sdshdr中的 buff[]指针, 并向外暴露, 而sdsdhr不对外 2.buff[]还是为以'\0'结尾, 以此兼容c 3.buff[]是个柔性数组, 其主要意义在于: a), 便于内存管理, 可以和sdshdr同时申请内存和释放 b), 便于扩容, 如果使用数组则无法扩容, 如果使用指针则无法进行统一的内存管理 c), 和sdshdr内存连续,...

atarik@163.com 544

深入理解跳跃链表在Redis中的应用

0.前言 前面写了一篇关于跳表基本原理和特性的文章,本次继续介绍跳表的概率平衡和工程实现,跳表在Redis、LevelDB、ES中都有应用,本文以Redis为工程蓝本,分析跳表在Redis中的工程实现。 通过本文你将了解到以下内容: Redis基本的数据类型和底层数据结构 Redis的有序集合的实现方法 Redis的跳表实现细节 1.Redis的数据结构 Redis对外共有约五种...

Z875983491的专栏 376

Redis 9种数据结构以及它们的内部编码实现

90%的人知道Redis 5种最基本的数据结构; 只有不到10%的人知道8种基本数据结构,5种基本+bitmap+GeoHash+HyperLogLog; 只有不到5%的人知道9种基本数据结构,5.0最新版本数据结构Streams; 只有不到1%的人掌握了所有9种基本数据结构以及8种内部编码; 掌握这篇文章的知识点,让你成为面试官眼中Redis方面最靓的仔! 说明:本文基于Redis-...

谢谢你,慌乱了我的年华 1926

Redis存储结构、数据类型

存储结构: Redis的全称是remote dictionary server(远程字典服务器),它以字典结构存储数据(key-value),并允许其他应用通过TCP协议读写字典中的内容。 数据结构如下: 数据类型: 1、字符类型 String 字符串类型是redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据。你可以用它...

开着奥迪卖小猪 7856

[每天进步一点点]Redis笔记:常用的基本数据类型

Redis常用的基本数据类型 激励:人人都有一个大厂的心,坚持自己的梦想,你就是世界。 乏味:笔记很无聊,需要去品味。 坚持:每天进步一点点,当知道的越多,才发现不知道的也越多。 String 最基本也是最常用的数据类型,也被叫做Binary-safe strings。 可以用来存储字符串、正数、浮点数。 操作命令 批量操作(原子性) mset key1 val1 key2 val2...

1197
上一篇: spring的自动装配
下一篇: 一次服务器被入侵的处理过程分享
java小姜在线冲
博客等级 码龄4年 53粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值