Redis系列:深刻理解高性能Redis的本质

【Redis】第4篇 深刻理解高性能Redis的本质 基于内存实现,而非磁盘,大都是简单的存取操作,资源主要消耗在 IO 上,所以读取速度快。数据结构:基于不同业务场景的高效数据结构动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)双端列表(REDIS_ENCODING_LINKEDLIST)压缩列表(REDIS_ENCODING_ZIPLIST)跳跃表(REDIS_ENCODING_SKIPLIST)哈希表(REDIS_HASH) 阅读详情

1 背景

分布式系统绕不开的核心之一就是数据缓存,有了缓存的支撑,系统的整体吞吐量会有很大的提升。通过使用缓存,我们把频繁查询的数据由磁盘调度到缓存中,保证数据的高效率读写。 当然,除了在内存内运行还远远不够,我们今天就以具有代表性的缓存中间件Redis为例子,分析下,它是如何达到飞起的效率。

2 Redis高效性能分析

Redis之所以能够提供超高的执行效率,主要从以下几个维度来实现的:

​

  • 存储模式:基于内存实现,而非磁盘

  • 数据结构:基于不同业务场景的高效数据结构动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)双端列表(REDIS_ENCODING_LINKEDLIST)压缩列表(REDIS_ENCODING_ZIPLIST)跳跃表(REDIS_ENCODING_SKIPLIST)哈希表(REDIS_HASH)整数集合(REDIS_ENCODING_INTSET)

  • 线程模型: Redis 的网络 IO 以及键值对指令读写是由单个线程来执行的,避免了不必要的contextswitch和竞选

  • I/O 模型: 基于I/O多路复用模型,非阻塞的I/O模型

  • 恰当的数据编码: 根据实际数据类型,选择合理的数据编码

2.1 官网的性能报告

Redis官方站点中,有对Redis性能做了比较详细的压测,可以参考官方这一篇 How fast is Redis?, 在较高的配置基准下(比如 8C 16G +),在连接数为0~10000的时候,最高QPS可达到120000。Redis以超过60000个连接为基准,仍然能够在这些条件下维持50000个q/s,体现了超高的性能。下图中横轴是连接数,纵轴是QPS。

​下面这张图为data size 与整体吞吐量之间的趋向关系:

​这个大概可以得出一个容量预估,比如你的服务用户量是多少,预估峰值QPS是多少,集群需要配置多少个实例(虽然实例的多少不能线性计算),可以大致推算出去。

2.2 基于内存实现

Redis的读写操作都是在内存中实现了,相对其他的持久化存储(如MySQL、File等,数据持久化在磁盘上),性能会高很多。因为我们在操作数据的时候,需要通过 IO 操作员先将数据读取到内存里,增加工作成本。

​上面那张图来源于网络,可以看看他的金字塔模型,越往上执行效率越高,价格也就越贵。下面给出每一层的执行耗时对比:

  • 寄存器:0.3 ns

  • L1高速缓存:0.9 ns

  • L2高速缓存:2.8 ns

  • L3高速缓存:12.9 ns

  • 主存:120 ns

  • 本地二级存储(SSD):50~150 us

  • 远程二级存储:30 ms 这样可能不直观,我们举个L1和SSD的对比,如果L1耗时1s的话,SSD中差不多要15~45小时。因为 CPU 内部集成了内存控制器,所以CPU直接控制了内存,给予通信上的最优带宽。上面的部分数据引用自《性能之巅:洞悉系统、企业与云计算》。

2.3 适配多元场景的高效数据结构

在 Redis 缓存中,常用的主要数据类型有五种,如下:

  • 字符串/REDIS_STRING:适用于 缓存、计数、共享Session、IP统计、分布式锁等。

  • 列表/REDIS_LIST: 链表、消息队列、栈、有序的对象列表(如朋友圈的点赞顺序列表、评论顺序列表)。

  • 哈希表/REDIS_HASH: 购物车信息、用户信息、Hash类型的(key, field, value)存储对象等。

  • 集合/REDIS_SET:无序的唯一的键值结构: 好友、关注者、粉丝、感兴趣的人集合等。

  • 有序集合/REDIS_ZSET:访问排行榜、点赞排行、粉丝数排行等。

上面这5种Redis 支持的数据类型,能够满足不同业务场景下的数据结构需求。而对于这几类数据类型的区分和支持,目的无非也是为了效率,具体的业务中使用恰当的数据结构才能保证得到应有的效率。

这5种数据类型都有一种或者多种数据结构来支撑,底层数据结构有 7 种。关系如下:

​限免我们对这些数据结构一个个的分析。

2.3.1 SDS 简单动态字符串

Redis使用简单动态字符串(simple dynamic string,SDS)来表示字符串,Redis中字符串类型包含的数据结构有:整数(R_INT) 、 字符串(R_RAW)。我们以字符串为例子,常规的字符串,比如 "Brand",如果要获取他的长度,需要从头开始遍历,直至遇到 \0 空字符代表结尾,如 C字符串。

C 字符串结构与 SDS 字符串结构 对比图 参照如下:

​

  • free属性的值为0,表示这个SDS没有分配任何未使用空间。

  • len属性的值为5,表示这个SDS保存了一个5字节长度的字符串。

  • buf是一个char类型的数组,存储真实的字符串,数组的前五个字节分别保存了'B'、'r'、'a'、'n'、'd'五个字符,而最后一个字节则保存了空字符'\0',代表结尾。 注意:SDS遵循C字符串的惯例以空字符结尾,保存空字符的1字节不计算在SDS的len属性中。

比起C字符串,SDS具有以下优点:

  1. 度获取字符串长度时间复杂度为O(1) 。 C字符串不记录自身长度,获取C字符串长度时必须遍历整个字符串计数得到,复杂度是O(N) SDS字符串自身记录维护len长度属性,获得SDS字符串长度的复杂度是O(1)

  2. 杜绝缓冲区溢出。 C字符串不记录长度,由于两个C字符串在内存存储上紧邻,在执行字符串拼接strcat时,如果不提前分配足够空间,很可能发生修改s1的数据溢出到s2所在的空间中(缓冲区溢出)。SDS杜绝了缓冲区溢出问题,它记录了长度,当修改SDS字符串之前,API都会检查SDS的空间是否满足修改的要求,不满足API会自动进行空间扩展。

  3. 空间预分配,减少修改时的内存重新分配次数 SDS 被修改后,程序不仅会变为 SDS 分配所需要的空间,还会分配额外的未使用空间。这样,Redis可以减少连续执行字符串增长操作所需的内存重分配次数。 具体分配使用空间如下2种方式:

  • 如修改后长度len小于1MB,就分配和len属性相同大小的未使用空间:free=len。

  • 如修改后长度len大于等于1MB,就分配1M的未使用空间:free=1MB。

  1. 惰性空间释放 惰性空间释放,缩短操作时:SDS避免了缩短字符串时所需的内存重分配操作,并为将来可能有的增长操作提供了优化。当SDS做缩短操作,不会立刻使用内存重分配来收回缩短后多出来的字节,而是保持在free属性里。将来如果需要 append 操作,则直接使用 free 中未使用的空间,减少了内存的分配步骤。 另外,SDS也提供了API手动进行释放SDS未使用空间,避免惰性释放策略会造成内存浪费。

  2. 二进制安全 C字符串的字符必须符合某种编码,除结尾空字符以外,字符串内部不允许有空字符串,存储有局限性。而在 Redis 中,不仅可以存储 String 类型的数据,也可能存储一些二进制数据。 二进制数据并不是规则的字符串格式,其中会包含一些特殊的字符如 '\0'。在 C 中遇到 '\0' 则表示字符串的结束,但SDS不是,它是以len长度标识结尾。

  3. 兼容部分C字符串函数。 SDS虽然是二进制安全的,但还是秉承C字符串以空字符结尾的特性,很多函数与C字符串一致不需要重写。

2.3.2 zipList 压缩列表

通过上面的数据结构关系图,可以看出,压缩列表是 List 、Hash、 Set 三种数据类型底层实现之一。 当我们的list列表数据量比较少的时候,且存储的数据轻量的(如小整数值、短字符串)时候, Redis 就会通过压缩列表来进行底层实现。 ziplist 是由一系列特殊编码的连续内存块组成的顺序型的数据结构,在列表头有三个字段 zlbytes、zltail 和 zllen,列表中有多个entry,表尾还有一个 zlend,我们来具体拆解下:

  • zlbytes:表示列表占用字节数

  • zltail:列表尾的偏移量

  • zllen:列表尾的偏移量:列表中的 entry 个数

  • entry:存储区,可以包含多个节点,每个节点可以存放整数或者字符串。

  • zlend:表示列表结束。

参考代码如下:

struct ziplist<T> {
    // 列表占用字节数
    int32 zlbytes;
	// 列表尾的偏移量,用于快速定位到最后一个节点
    int32 zltail_offset; 
	// 列表entry元素个数
    int16 zllength; 
	// 元素内容列表
    T[] entries; 
	// 标志压缩列表的结束,值恒为 0xFF
    int8 zlend; 
}

​如果查找定位首个元素或最后1个元素,可以通过表头zlbytes、zltail_offset元素快速获取,复杂度是 O(1)。但是查找其他元素时,就没有这么高效了,只能逐个查找下去,比如 entry n 的复杂度就是 O(N)。

2.3.3 linklist 双端列表

Redis List 数据类型经常使用在链表、消息队列、栈、有序的对象列表(如朋友圈的点赞顺序列表、评论顺序列表、关注时间线)等场景,无论是队列(先进先出),还是栈(先进后出),双端列表都能很好的支持。 参考代码如下:

typedef struct list {
	// 表头
	listnode * head;
	// 表尾
	listnode * tail;
	// 链表所包含的节点数量
	unsigned long len;
	// 函数:复制节点值
	void *(*dup)(void *ptr);
	// 函数:释放节点值
	void (*free)(void *ptr);
	// 函数:对比节点值
	int (*match)(void *ptr, void *key);
} list;

Redis 的链表实现的特性可以总结如下:

  • 双端:链表节点带有 prev 和 next 指针,获取某个节点的前一节点和后一节点的复杂度都是 O(1)。

  • 无环:表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL,对链表的访问以 NULL 为终点。

  • 表头指针/表尾指针:通过 list 结构的 head 指针和 tail 指针,获取链表的表头节点和表尾节点的复杂度为 O(1)。

  • 链表长度计数器:通过 list 结构的 len 属性来对 list 的链表节点进行计数,获取节点数量的复杂度为O(1)。

  • 多态:链表节点使用 void* 指针来保存节点值,并通过 list 结构的 dup、free、match 三个属性为节点值设置类型特定函数,所以链表可以用于保存各种不同类型的值。 使用链表的附加空间相对太高,因为64bit系统中指针是8个字节,所以prev和next指针需要占据16个字节,且链表节点在内存中单独分配,会加剧内存的碎片化,影响内存管理效率。考虑到链表的以上缺点,Redis后续版本对列表数据结构进行改造,使用quicklist代替了ziplist和linkedlist。 作为ziplist 和 linkedlist 的混合体,它将 linkedlist 按段切分,每一段使用 ziplist 来紧凑存储,多个 ziplist 之间使用双向指针串接起来。这样,性能就的得到了更大的提升。

2.3.4 Hhash 字典

无论何种类型(string、list、hash、set、zset),Redis都是以一个Hash结构的形式来保存键值对的。整体是一个数组,数组中的每个元素都是一个独立的对象,被称为哈系桶,比如图中1 ~ n, 对应的entry保存着实际具体值的指针。

​上图中的全局哈希表,它的时间复杂度是 O(1),只需要计算每个键的哈希值,便知道对应的哈希桶位置,定位桶中的 entry ,并找到对应数据。这个执行效率就很高了。 为了解决可能存在的冲突,采用了链式哈希的做法,也就是同一个桶里面的元素使用链表保存。

2.3.5 intset 整数集合

如果你的集合只有整数值元素,并且数量是轻量的,这时候Redis会使用使用整数集合作为Redis集合的底层数据结构。参考如下代码:

typedef struct intset{
     // 编码格式
     uint32_t encoding;
     // 集合中的元素个数
     uint32_t length;
     // 保存元素数据
     int8_t contents[];
} intset;

我们拆解下:

  • encoding: 编码方式

  • length: 数组中元素个数,也就是数组的整体长度

  • contents[]: 整数集合,集合的每个元素都是数组的一个数组项(item)。具有以下特点:按值的大小增序排列不包含任何重复项

2.3.6 skipList 跳跃表

skiplist(即跳跃表)是一种有序数据结构,所以它也是ZSet数据类型中的一种,通过在每个节点中维持多个指向其他节点的指针,达到快速定位的目标。 跳跃表的平均的节点搜索,平均时间复杂度是 O(logN)、最差时间复杂度是 O(N),还可以通过顺序性操作来批量处理节点。 跳跃表是基于链表的改良,在它基础上,增加了多层级索引,通过索引不断跳转,最终定好位到真实的数据项。这个方式是不是让大家想到b+tree,理念上有点接近,如下图所示:

​可以看出,需要获取 68 这个元素需要经历3次查找,需要获取 97则需要经历4次查找。

2.4 单线程模型

Redis 的单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。 但Redis的其他功能, 比如持久化、异步删除、集群数据同步等等,其实是由额外的线程执行的。 可以这么说,Redis工作线程是单线程的。但是,整个Redis来说,是多线程的。

2.4.1 为何是单线程?

那在主流程中使用单线程,主要是出于什么原因呢?

  • 整体吞吐量降低 适当的扩增线程,是为了有效的利用cpu的性能,让它跟内存达到一个利用的最优值。但频繁的Redis读写,如果没有对线程进行有效管理,不但对系统的吞吐量没有提升,反而可能导致下降。

  • CPU上下文切换 在运行任务的时候,CPU需要把任务加载到CPU寄存器中进行计算,当切换到其他thread时,需要将当前上下文存储在系统内核中,以便后续重新执行计算时再次加载。就像你做专心做一件事时,频繁切换,频繁被打断,这个代价是非常高的。如图中,切换上下文时,我们需要完成一系列工作,save context、switch、restore context等,这种操作越频繁越是耗费资源。

  • 共享资源的并发控制问题 引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度。同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。

  • 内存才是核心关注点 对于 Redis 框架来说, 主要的性能瓶颈是内存或者网络带宽,而非 CPU。

2.4.2 单线程的好处

  1. 避免线程创建过多导致的性能消耗,反而降低整体吞吐能力。

  2. 避免上下文切换引起的 CPU 额外的开销。

  3. 避免了线程之间的竞争问题,如加锁、解锁、死锁等,都会造成性能损耗。

  4. 无需额外考虑多线程带来的程序复杂度,代码更清晰,处理逻辑简单。

2.4.3 单线程是否有效利用CPU

官方这么说

It’s not very frequent that CPU becomes your bottleneck with Redis, as usually Redis is either memory or network bound. For instance, using pipelining Redis running on an average Linux system can deliver even 1 million requests per second, so if your application mainly uses O(N) or O(log(N)) commands, it is hardly going to use too much CPU.

大概意思是,Redis是完全的纯内存操作,执行速度是非常快的,CPU通常不会是瓶颈,因为大多数请求不会是CPU密集型的。参考 Redis真正的性能瓶颈在网络IO,也就是客户端和服务端之间的网络传输延迟,因此Redis选择了单线程的IO多路复用来实现它的核心网络模型。

2.5 I/O 多路复用模型

服务端网络编程常见的 I/O 模型有四种:同步阻塞IO(Blocking IO)、同步非阻塞IO(Non-blocking IO)、IO多路复用(IO Multiplexing)、异步IO(Asynchronous IO)。 Redis 采用的是 I/O 多路复用技术,并发的去处理连接,它的多路复用程序函数有 select、poll、epoll、kqueue。以 epoll (目前最新的也是最好的多路复用技术)函数为例,当客服端执行 read、write、accept、close 等操作命令时,它会将命令封装成一个个事件,然后利用 epoll 多路复用的特性来避免 I/O 阻塞。 下面我们看看普通 I/O 模型 和 Redis的 I/O 多路复模型的的区别,来分析Redis高频请求下如何保持高效执行。

2.5.1 普通 I/O 模型

先来看一下传统的阻塞 I/O 模型到底是如何工作的:当使用 read 或者 write 对某一个文件描述符(File Descriptor:FD)进行读写时,如果当前 FD 不可读或不可写,整个 Redis 服务就不会对其它的操作作出响应,导致整个服务不可用。 这也就是传统意义上的,也就是我们在编程中使用最多的阻塞模型:

​阻塞模型虽然开发中非常常见也非常易于理解,但是由于它会影响其他 FD 对应的服务,所以在需要处理多个客户端任务的时候,往往都不会使用阻塞模型。

2.5.2 I/O 多路复用

​多路 复用指的是:多个socket连接复用一个线程。这种模式下,内核不会去监视应用程序的连接,而是监视文件描述符。 当客户端发起请求的时候,会生成不同事件类型的套接字。而在服务端,因为使用了 I/O 多路复用技术,所以不是阻塞式的同步执行,而是将消息放入 socket 队列(参考下图的 I/O Multiplexing module),然后通过 File event Dispatcher 将其转发到不同的事件处理器上,如accept、read、send。

综上,我们得出如下特性:

  • 单线程模式,内核持续监听 socket 上的连接及数据请求,一监听就交予Redis线程处理,达到单个线程处理多个I/O 流的效果。

  • epoll 提供了基于事件的回调机制。不同事件调用对应的事件处理器。Redis可以持续性的高效处理事件,性能同步提升。

  • Redis 不阻塞任一客户端发起的请求,所以可以同时和多个客户端连接并处理请求,聚币并发执行的能力。

3 高性能Redis总结

  • 基于内存实现,而非磁盘,大都是简单的存取操作,资源主要消耗在 IO 上,所以读取速度快。

  • 数据结构:基于不同业务场景的高效数据结构动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)双端列表(REDIS_ENCODING_LINKEDLIST)压缩列表(REDIS_ENCODING_ZIPLIST)跳跃表(REDIS_ENCODING_SKIPLIST)哈希表(REDIS_HASH)整数集合(REDIS_ENCODING_INTSET)

  • 线程模型:Redis 的网络 IO 以及键值对指令读写是由单个线程来执行的,避免了不必要的contextswitch和竞选

  • I/O 模型:基于I/O多路复用模型,非阻塞的I/O模型

  • 恰单的数据编码:根据实际数据类型,选择合理的数据编码

  • Redis 本身是一个全局 哈希表,他的时间复杂度是 O(1),另外为了防止哈希冲突导致链表过长,执行 rehash 操作进行扩充,减少哈希冲突。

Redis系列2:数据持久化提高可用性 从上一篇的 《深刻理解高性能Redis的本质》 中可以知道, 我们经常在数据库层上加一层缓存(如Redis),来保证数据的访问效率。这样性能确实也有了大幅度的提升,但是本身Redis也是一层服务,也存在宕机、故障的可能性。一旦服务挂起,可能生产的后果包括如下几方面:1、Redis的数据是存在内存中的,所以一旦挂起,内存中的数据会全部丢失。2、I/O从内存层级迁移到磁盘层级,性能极速下降。3、原本访问缓存的请求会透过缓存层直接投向数据库,给数据库带来极大的压力,甚至导致雪崩。 阅读详情

相关推荐

ENVI5.6+SARscape实战:基于哨兵一号的PS与SBAS时序InSAR地表形变监测全流程解析

本文详细解析了使用ENVI5.6和SARscape软件基于哨兵一号数据进行PS与SBAS时序InSAR地表形变监测的全流程。从数据获取、预处理到PS-InSAR和SBAS-InSAR处理,提供了实用技巧和优化建议,帮助用户高效完成地表形变监测任务。

weixin_29245767的博客 1151

redis学习笔记

 什么是redis?redis 是一个基于内存的高性能key-value数据库。 (有空再补充,有理解错误或不足欢迎指正)Reids的特点Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构

yiihsia的学习阵地 7661

Zephyr、FreeRTOS 和 RT-Thread

你是…更适合用嵌入式新手,刚接触 RTOSFreeRTOS(入门简单)IoT 项目开发,需要 BLE/WiFi/MQTTZephyr(协议全)想快速构建可部署的产品Zephyr(模块统一)只做单个任务或简单状态机控制FreeRTOS(轻量)做平台化、持续集成、自动测试Zephyr(CI 支持强)

is0815的博客 2240

redis、本质、数据、主从、雪崩

1.1 什么是redis? redis本质是一个Key–Value类型的内存数据库 整个数据库加载到内存中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存 因为是内存操作,redis的性能非常出色,每秒可以处理超过10万次读写操作,是最快的key-values数据库 1.2 redis特点 ​ redis为什么快? 纯内存操作 单线称避免上下文切换 非阻塞IO多路复用机制 redis缺点 内存限制,不能用作海量数据储存 1.3 redis五种数据类型 ​ 说明: r

weixin_53614310的博客 236

PID、模糊PID、SkyHook、LQR、H2/H∞、ADRC等悬架控制合集

PID、模糊PID、SkyHook、LQR、H2/H∞等悬架控制合集

Mr.邹的博客 2013

手把手教你学Simulink--进阶电机控制场景实例:基于Simulink的直流电机双闭环调速系统抗负载扰动仿真

摘要:本文基于Simulink平台构建直流电机双闭环调速系统,重点研究其在工业传送带场景下的抗负载扰动性能。系统采用转速外环(稳速)和电流内环(限流)的嵌套结构,通过工程法整定PI参数,实现了转速跌落<10%、恢复时间<0.5s的优异抗扰性能。仿真结果表明,相比单闭环系统,双闭环控制使转速跌落率降低47%,恢复时间缩短75%。文中详细介绍了数学模型建立、Simulink模块实现及参数优化方法,并提供了完整代码和模型文件,为电机控制系统设计提供实用参考。

MHD0815的博客 179

Redis背景知识

本文详解 Redis:它是基于内存的键值对 NoSQL 数据库,由开发者为优化网站自研并开源,现成为后端必备工具。其核心特性包括支持多数据结构(如哈希、有序集合)、内置键过期 / 发布订阅等功能、通过持久化防数据丢失,还能以集群 + 主从复制支撑分布式系统。 Redis 的 “快” 源于内存存储(比硬盘快 10 万倍)、逻辑极简、IO 多路复用 + 单线程模型降开销。实战中可做热点缓存(提速系统)、分布式 Session(解登录串号)、轻量消息队列(解耦削峰)、实时数据处理,但不适合存大规模 / 冷数据(内

nplplus的博客 894

PCL RANSAC拟合空间圆【2026最新版】

RANSAC三维点云空间3D圆拟合。博客长期更新,本文最新更新时间为:2026年4月13日。代码在PCL1.15.0中测试通过

点云侠的博客 7453

redis持久化rdb和aof

redis本地化主要有两种,分别是aof、rdb aof 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。Redis 还可以同时使用 AO

ai2713165的博客 1268

一文就够-InfiniBand 技术全面解析:从原理到实践的通俗易懂指南

想象一下,在一个超级数据中心里,成千上万台服务器需要像蜜蜂群体一样高效协作。如果用传统的网络连接,就像让每只蜜蜂都排着队传递消息,效率极低。InfiniBand(简称 IB)就是为了解决这种 "通信拥堵" 而生的高速网络技术,它专门为高性能计算(HPC)、数据中心和云计算环境设计,就像给服务器之间搭建了多条高速公路,让数据可以飞驰而过。

jundao1997的专栏 1394

Python控制LitePoint IQxel-MW 无线网络测试仪

由于项目需要进行WIFI和BT(蓝牙)的射频测试,所以需要开发一款支持WIFI/BT射频测试的工具。开发射频测试工具的话那肯定离不开仪表的控制。我们项目用的就Litepoint的IQxel-MW无线网络测试仪。这篇文章主要就是介绍一下如何控制仪表以及实现的过程!LitePoint是美国硅谷的一家仪器厂商,主要做一些无线通讯测试仪表,包括WIFI,BT(Bluetooth),LTE等等。

xgh1951的博客 1万+

Redis 是什么?

Redis使用场景   1 Redis 是什么?     通常而言目前的数据库分类有几种,包括 SQL/NSQL,,关系数据库,键值数据库等等 等,分类的标准也不以,Redis本质上也是一种键值数据库的,但它在保持键值数据库简单快捷特点的同时,又吸收了部分关系数据库的优点。从而使它的位置处于关系数据库和键值数 据库之间。Redis不仅能保存Strings类型的数据,还能保存Li

白及 1675

slew dreate,slew threshold与transition计算

​只看rise情况下,from pin取slew threshold10%-90%的区间,slew derate为1,计算得到transition为1.002e-10,to pin的slew threshold 为30%-70%,slew derate 0.5,从波形列表上取相近的值3.75e-10和8.75e-10,计算得到transition为(8.75e-10-3.75e-10)/0.5=1e-9,考虑精度和取值区间问题,基本符合工具计算的值,如下:​。如下示例,在.lib库中有定义以下内容。

m0_61544122的博客 791

Redis系列1:深刻理解高性能Redis的本质

当客户端发起请求的时候,会生成不同事件类型的套接字。而在服务端,因为使用了 I/O 多路复用技术,所以不是阻塞式的同步执行,而是将消息放入 socket 队列(参考下图的 I/O Multiplexing module),然后通过 File event Dispatcher 将其转发到不同的事件处理器上,如accept、read、send。

Ly768768的博客 1190

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

深度学习工具包 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实战宝典:深刻理解高性能Redis的本质

分布式系统绕不开的核心之一的就是数据缓存,有了缓存的支撑,系统的整体吞吐量会有很大的提升。通过使用缓存,我们把频繁查询的数据由磁盘调度到缓存中,保证数据的高效率读写。当然,除了在内存内运行还远远不够,我们今天就以具有代表性的缓存中间件Redis为例子,分析下,它是如何达到飞起的效率。

无休居士的博客 1912

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

追求性能极致 - Redis:深刻理解高性能Redis的本质

基于内存实现,而非磁盘,大都是简单的存取操作,资源主要消耗在 IO 上,所以读取速度快。数据结构:基于不同业务场景的高效数据结构动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)双端列表(REDIS_ENCODING_LINKEDLIST)压缩列表(REDIS_ENCODING_ZIPLIST)跳跃表(REDIS_ENCODING_SKIPLIST)哈希表(REDIS_HASH)

smart_an的专栏 1060

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深刻理解高性能Redis的本质

而在服务端,因为使用了 I/O 多路复用技术,所以不是阻塞式的同步执行,而是将消息放入 socket 队列(参考下图的 I/O Multiplexing module),然后通过 File event Dispatcher 将其转发到不同的事件处理器上,如accept、read、send。通过使用缓存,我们把频繁查询的数据由磁盘调度到缓存中,保证数据的高效率读写。上图中的全局哈希表,它的时间复杂度是 O(1),只需要计算每个键的哈希值,便知道对应的哈希桶位置,定位桶中的 entry ,并找到对应数据。

mfmfmfo的博客 175

深刻理解redis高性能之IO多路复用

下面就是IO多路复用的核心。

m0_71031876的博客 1192

从Redis set的各种使用场景来深刻理解它

从使用场景深刻理解redis set的特点

qq_17858343的博客 1222

Redis系列:Bitmap实现亿万级数据计算

我们在篇深刻理解高性能Redis的本质动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)双端列表(REDIS_ENCODING_LINKEDLIST)压缩列表(REDIS_ENCODING_ZIPLIST)跳跃表(REDIS_ENCODING_SKIPLIST)哈希表(REDIS_HASH)整数集合(REDIS_ENCODING_INTSET)

Ly768768的博客 1659

Redis系列:HyperLogLog实现海量数据基数统计

我们来回顾下在这个系列的篇深刻理解高性能Redis的本质中介绍过Redis的几种基本数据结构,动态字符串(REDIS_STRING):整数(REDIS_ENCODING_INT)、字符串(REDIS_ENCODING_RAW)双端列表(REDIS_ENCODING_LINKEDLIST)压缩列表(REDIS_ENCODING_ZIPLIST)跳跃表(REDIS_ENCODING_SKIPLIST)哈希表(REDIS_HASH)整数集合(REDIS_ENCODING_INTSET)

Ly768768的博客 1184

如何深刻理解Redis的底层原理?Redis的运行机制是什么?如何优化Redis提供更高效服务

客户端在操作的时候,会产生具有不同事件类型的socket,Redis通过事件循环机制不断地检查每个连接的状态,当有事件发生时,就会触发回调。Redis将传入的每条数据首先存入内存中,这样可以显著减少对持久存储的访问时间,从而提高数据检索性能,由于Redis基于内存操作,CPU不是性能瓶颈,机器的内存和宽带才是Redis的瓶颈。3. IO多路复用机制:Redis利用非阻塞的IO多路复用技术(如epoll/select/kqueue等),在单线程中轮询多个socket,从而能够同时处理多个客户端的请求。

zhang9880000的博客 1494
上一篇: 优雅停止 SpringBoot 服务,拒绝 kill -9 暴力停止
下一篇: SQL优化篇:如何成为一位写优质SQL语句的绝顶高手
Java佳佳
博客等级 码龄4年 216粉丝 286原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值