【面试收藏】Redis最全面试题

出自:https://github.com/CyC2018/CS-Notes

程序员乔戈里整理

  • 一、概述

  • 二、数据类型

    • STRING

    • LIST

    • SET

    • HASH

    • ZSET

  • 三、数据结构

    • 字典

    • 跳跃表

  • 四、使用场景

    • 计数器

    • 缓存

    • 查找表

    • 消息队列

    • 会话缓存

    • 分布式锁实现

    • 其它

  • 五、Redis 与 Memcached

    • 数据类型

    • 数据持久化

    • 分布式

    • 内存管理机制

  • 六、键的过期时间

  • 七、数据淘汰策略

  • 八、持久化

    • RDB 持久化

    • AOF 持久化

  • 九、事务

  • 十、事件

    • 文件事件

    • 时间事件

    • 事件的调度与执行

  • 十一、复制

    • 连接过程

    • 主从链

  • 十二、Sentinel

  • 十三、分片

  • 十四、一个简单的论坛系统分析

    • 文章信息

    • 点赞功能

    • 对文章进行排序

  • 参考资料

一、概述

Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。

键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。

Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能,使用分片来扩展写性能。

二、数据类型

数据类型可以存储的值操作
STRING字符串、整数或者浮点数对整个字符串或者字符串的其中一部分执行操作
对整数和浮点数执行自增或者自减操作
LIST列表从两端压入或者弹出元素 
对单个或者多个元素
进行修剪,只保留一个范围内的元素
SET无序集合添加、获取、移除单个元素
检查一个元素是否存在于集合中
计算交集、并集、差集
从集合里面随机获取元素
HASH包含键值对的无序散列表添加、获取、移除单个键值对
获取所有键值对
检查某个键是否存在
ZSET有序集合添加、获取、删除元素
根据分值范围或者成员来获取元素
计算一个键的排名

What Redis data structures look like

STRING

> set hello world
OK
> get hello
"world"
> del hello
(integer) 1
> get hello
(nil)

LIST

> rpush list-key item
(integer) 1
> rpush list-key item2
(integer) 2
> rpush list-key item
(integer) 3> lrange list-key 0 -1
1) "item"
2) "item2"
3) "item"> lindex list-key 1
"item2"> lpop list-key
"item"> lrange list-key 0 -1
1) "item2"
2) "item"

SET

> sadd set-key item
(integer) 1
> sadd set-key item2
(integer) 1
> sadd set-key item3
(integer) 1
> sadd set-key item
(integer) 0> smembers set-key
1) "item"
2) "item2"
3) "item3"> sismember set-key item4
(integer) 0
> sismember set-key item
(integer) 1> srem set-key item2
(integer) 1
> srem set-key item2
(integer) 0> smembers set-key
1) "item"
2) "item3"

HASH

> hset hash-key sub-key1 value1
(integer) 1
> hset hash-key sub-key2 value2
(integer) 1
> hset hash-key sub-key1 value1
(integer) 0> hgetall hash-key
1) "sub-key1"
2) "value1"
3) "sub-key2"
4) "value2"> hdel hash-key sub-key2
(integer) 1
> hdel hash-key sub-key2
(integer) 0> hget hash-key sub-key1
"value1"> hgetall hash-key
1) "sub-key1"
2) "value1"

ZSET

> zadd zset-key 728 member1
(integer) 1
> zadd zset-key 982 member0
(integer) 1
> zadd zset-key 982 member0
(integer) 0> zrange zset-key 0 -1 withscores
1) "member1"
2) "728"
3) "member0"
4) "982"> zrangebyscore zset-key 0 800 withscores
1) "member1"
2) "728"> zrem zset-key member1
(integer) 1
> zrem zset-key member1
(integer) 0> zrange zset-key 0 -1 withscores
1) "member0"
2) "982"

三、数据结构

字典

dictht 是一个散列表结构,使用拉链法保存哈希冲突。

/* This is our hash table structure. Every dictionary has two of this as we* implement incremental rehashing, for the old to the new table. */
typedef struct dictht {dictEntry **table;unsigned long size;unsigned long sizemask;unsigned long used;
} dictht;
typedef struct dictEntry {void *key;union {void *val;uint64_t u64;int64_t s64;double d;} v;struct dictEntry *next;
} dictEntry;

Redis 的字典 dict 中包含两个哈希表 dictht,这是为了方便进行 rehash 操作。在扩容时,将其中一个 dictht 上的键值对 rehash 到另一个 dictht 上面,完成之后释放空间并交换两个 dictht 的角色。

typedef struct dict {dictType *type;void *privdata;dictht ht[2];long rehashidx; /* rehashing not in progress if rehashidx == -1 */unsigned long iterators; /* number of iterators currently running */
} dict;

rehash 操作不是一次性完成,而是采用渐进方式,这是为了避免一次性执行过多的 rehash 操作给服务器带来过大的负担。

渐进式 rehash 通过记录 dict 的 rehashidx 完成,它从 0 开始,然后每执行一次 rehash 都会递增。例如在一次 rehash 中,要把 dict[0] rehash 到 dict[1],这一次会把 dict[0] 上 table[rehashidx] 的键值对 rehash 到 dict[1] 上,dict[0] 的 table[rehashidx] 指向 null,并令 rehashidx++。

在 rehash 期间,每次对字典执行添加、删除、查找或者更新操作时,都会执行一次渐进式 rehash。

采用渐进式 rehash 会导致字典中的数据分散在两个 dictht 上,因此对字典的查找操作也需要到对应的 dictht 去执行。

/* Performs N steps of incremental rehashing. Returns 1 if there are still* keys to move from the old to the new hash table, otherwise 0 is returned.** Note that a rehashing step consists in moving a bucket (that may have more* than one key as we use chaining) from the old to the new hash table, however* since part of the hash table may be composed of empty spaces, it is not* guaranteed that this function will rehash even a single bucket, since it* will visit at max N*10 empty buckets in total, otherwise the amount of* work it does would be unbound and the function may block for a long time. */
int dictRehash(dict *d, int n) {int empty_visits = n * 10; /* Max number of empty buckets to visit. */if (!dictIsRehashing(d)) return 0;while (n-- && d->ht[0].used != 0) {dictEntry *de, *nextde;/* Note that rehashidx can't overflow as we are sure there are more* elements because ht[0].used != 0 */assert(d->ht[0].size > (unsigned long) d->rehashidx);while (d->ht[0].table[d->rehashidx] == NULL) {d->rehashidx++;if (--empty_visits == 0) return 1;}de = d->ht[0].table[d->rehashidx];/* Move all the keys in this bucket from the old to the new hash HT */while (de) {uint64_t h;nextde = de->next;/* Get the index in the new hash table */h = dictHashKey(d, de->key) & d->ht[1].sizemask;de->next = d->ht[1].table[h];d->ht[1].table[h] = de;d->ht[0].used--;d->ht[1].used++;de = nextde;}d->ht[0].table[d->rehashidx] = NULL;d->rehashidx++;}/* Check if we already rehashed the whole table... */if (d->ht[0].used == 0) {zfree(d->ht[0].table);d->ht[0] = d->ht[1];_dictReset(&d->ht[1]);d->rehashidx = -1;return 0;}/* More to rehash... */return 1;
}

跳跃表

是有序集合的底层实现之一。

跳跃表是基于多指针有序链表实现的,可以看成多个有序链表。

在查找时,从上层指针开始查找,找到对应的区间之后再到下一层去查找。下图演示了查找 22 的过程。

与红黑树等平衡树相比,跳跃表具有以下优点:

  • 插入速度非常快速,因为不需要进行旋转等操作来维护平衡性;

  • 更容易实现;

  • 支持无锁操作。

四、使用场景

计数器

可以对 String 进行自增自减运算,从而实现计数器功能。

Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。

缓存

将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。

查找表

例如 DNS 记录就很适合使用 Redis 进行存储。

查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠的数据来源。

消息队列

List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息

不过最好使用 Kafka、RabbitMQ 等消息中间件。

会话缓存

可以使用 Redis 来统一存储多台应用服务器的会话信息。

当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。

分布式锁实现

在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。

可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。

其它

Set 可以实现交集、并集等操作,从而实现共同好友等功能。

ZSet 可以实现有序性操作,从而实现排行榜等功能。

五、Redis 与 Memcached

两者都是非关系型内存键值数据库,主要有以下不同:

数据类型

Memcached 仅支持字符串类型,而 Redis 支持五种不同的数据类型,可以更灵活地解决问题。

数据持久化

Redis 支持两种持久化策略:RDB 快照和 AOF 日志,而 Memcached 不支持持久化。

分布式

Memcached 不支持分布式,只能通过在客户端使用一致性哈希来实现分布式存储,这种方式在存储和查询时都需要先在客户端计算一次数据所在的节点。

Redis Cluster 实现了分布式的支持。

内存管理机制

  • 在 Redis 中,并不是所有数据都一直存储在内存中,可以将一些很久没用的 value 交换到磁盘,而 Memcached 的数据则会一直在内存中。

  • Memcached 将内存分割成特定长度的块来存储数据,以完全解决内存碎片的问题。但是这种方式会使得内存的利用率不高,例如块的大小为 128 bytes,只存储 100 bytes 的数据,那么剩下的 28 bytes 就浪费掉了。

六、键的过期时间

Redis 可以为每个键设置过期时间,当键过期时,会自动删除该键。

对于散列表这种容器,只能为整个键设置过期时间(整个散列表),而不能为键里面的单个元素设置过期时间。

七、数据淘汰策略

可以设置内存最大使用量,当内存使用量超出时,会施行数据淘汰策略。

Redis 具体有 6 种淘汰策略:

策略描述
volatile-lru从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
volatile-ttl从已设置过期时间的数据集中挑选将要过期的数据淘汰
volatile-random从已设置过期时间的数据集中任意选择数据淘汰
allkeys-lru从所有数据集中挑选最近最少使用的数据淘汰
allkeys-random从所有数据集中任意选择数据进行淘汰
noeviction禁止驱逐数据

作为内存数据库,出于对性能和内存消耗的考虑,Redis 的淘汰算法实际实现上并非针对所有 key,而是抽样一小部分并且从中选出被淘汰的 key。

使用 Redis 缓存数据时,为了提高缓存命中率,需要保证缓存数据都是热点数据。可以将内存最大使用量设置为热点数据占用的内存量,然后启用 allkeys-lru 淘汰策略,将最近最少使用的数据淘汰。

Redis 4.0 引入了 volatile-lfu 和 allkeys-lfu 淘汰策略,LFU 策略通过统计访问频率,将访问频率最少的键值对淘汰。

八、持久化

Redis 是内存型数据库,为了保证数据在断电后不会丢失,需要将内存中的数据持久化到硬盘上。

RDB 持久化

将某个时间点的所有数据都存放到硬盘上。

可以将快照复制到其它服务器从而创建具有相同数据的服务器副本。

如果系统发生故障,将会丢失最后一次创建快照之后的数据。

如果数据量很大,保存快照的时间会很长。

AOF 持久化

将写命令添加到 AOF 文件(Append Only File)的末尾。

使用 AOF 持久化需要设置同步选项,从而确保写命令什么时候会同步到磁盘文件上。这是因为对文件进行写入并不会马上将内容同步到磁盘上,而是先存储到缓冲区,然后由操作系统决定什么时候同步到磁盘。有以下同步选项:

选项同步频率
always每个写命令都同步
everysec每秒同步一次
no让操作系统来决定何时同步
  • always 选项会严重减低服务器的性能;

  • everysec 选项比较合适,可以保证系统崩溃时只会丢失一秒左右的数据,并且 Redis 每秒执行一次同步对服务器性能几乎没有任何影响;

  • no 选项并不能给服务器性能带来多大的提升,而且也会增加系统崩溃时数据丢失的数量。

随着服务器写请求的增多,AOF 文件会越来越大。Redis 提供了一种将 AOF 重写的特性,能够去除 AOF 文件中的冗余写命令。

九、事务

一个事务包含了多个命令,服务器在执行事务期间,不会改去执行其它客户端的命令请求。

事务中的多个命令被一次性发送给服务器,而不是一条一条发送,这种方式被称为流水线,它可以减少客户端与服务器之间的网络通信次数从而提升性能。

Redis 最简单的事务实现方式是使用 MULTI 和 EXEC 命令将事务操作包围起来。

十、事件

Redis 服务器是一个事件驱动程序。

文件事件

服务器通过套接字与客户端或者其它服务器进行通信,文件事件就是对套接字操作的抽象。

Redis 基于 Reactor 模式开发了自己的网络事件处理器,使用 I/O 多路复用程序来同时监听多个套接字,并将到达的事件传送给文件事件分派器,分派器会根据套接字产生的事件类型调用相应的事件处理器。

时间事件

服务器有一些操作需要在给定的时间点执行,时间事件是对这类定时操作的抽象。

时间事件又分为:

  • 定时事件:是让一段程序在指定的时间之内执行一次;

  • 周期性事件:是让一段程序每隔指定时间就执行一次。

Redis 将所有时间事件都放在一个无序链表中,通过遍历整个链表查找出已到达的时间事件,并调用相应的事件处理器。

事件的调度与执行

服务器需要不断监听文件事件的套接字才能得到待处理的文件事件,但是不能一直监听,否则时间事件无法在规定的时间内执行,因此监听时间应该根据距离现在最近的时间事件来决定。

事件调度与执行由 aeProcessEvents 函数负责,伪代码如下:

def aeProcessEvents():# 获取到达时间离当前时间最接近的时间事件time_event = aeSearchNearestTimer()# 计算最接近的时间事件距离到达还有多少毫秒remaind_ms = time_event.when - unix_ts_now()# 如果事件已到达,那么 remaind_ms 的值可能为负数,将它设为 0if remaind_ms < 0:remaind_ms = 0# 根据 remaind_ms 的值,创建 timevaltimeval = create_timeval_with_ms(remaind_ms)# 阻塞并等待文件事件产生,最大阻塞时间由传入的 timeval 决定aeApiPoll(timeval)# 处理所有已产生的文件事件procesFileEvents()# 处理所有已到达的时间事件processTimeEvents()

将 aeProcessEvents 函数置于一个循环里面,加上初始化和清理函数,就构成了 Redis 服务器的主函数,伪代码如下:

def main():# 初始化服务器init_server()# 一直处理事件,直到服务器关闭为止while server_is_not_shutdown():aeProcessEvents()# 服务器关闭,执行清理操作clean_server()

从事件处理的角度来看,服务器运行流程如下:

十一、复制

通过使用 slaveof host port 命令来让一个服务器成为另一个服务器的从服务器。

一个从服务器只能有一个主服务器,并且不支持主主复制。

连接过程

  1. 主服务器创建快照文件,发送给从服务器,并在发送期间使用缓冲区记录执行的写命令。快照文件发送完毕之后,开始向从服务器发送存储在缓冲区中的写命令;

  2. 从服务器丢弃所有旧数据,载入主服务器发来的快照文件,之后从服务器开始接受主服务器发来的写命令;

  3. 主服务器每执行一次写命令,就向从服务器发送相同的写命令。

主从链

随着负载不断上升,主服务器可能无法很快地更新所有从服务器,或者重新连接和重新同步从服务器将导致系统超载。为了解决这个问题,可以创建一个中间层来分担主服务器的复制工作。中间层的服务器是最上层服务器的从服务器,又是最下层服务器的主服务器。

十二、Sentinel

Sentinel(哨兵)可以监听集群中的服务器,并在主服务器进入下线状态时,自动从从服务器中选举出新的主服务器。

十三、分片

分片是将数据划分为多个部分的方法,可以将数据存储到多台机器里面,这种方法在解决某些问题时可以获得线性级别的性能提升。

假设有 4 个 Redis 实例 R0,R1,R2,R3,还有很多表示用户的键 user:1,user:2,... ,有不同的方式来选择一个指定的键存储在哪个实例中。

  • 最简单的方式是范围分片,例如用户 id 从 0~1000 的存储到实例 R0 中,用户 id 从 1001~2000 的存储到实例 R1 中,等等。但是这样需要维护一张映射范围表,维护操作代价很高。

  • 还有一种方式是哈希分片,使用 CRC32 哈希函数将键转换为一个数字,再对实例数量求模就能知道应该存储的实例。

根据执行分片的位置,可以分为三种分片方式:

  • 客户端分片:客户端使用一致性哈希等算法决定键应当分布到哪个节点。

  • 代理分片:将客户端请求发送到代理上,由代理转发请求到正确的节点上。

  • 服务器分片:Redis Cluster。

十四、一个简单的论坛系统分析

该论坛系统功能如下:

  • 可以发布文章;

  • 可以对文章进行点赞;

  • 在首页可以按文章的发布时间或者文章的点赞数进行排序显示。

文章信息

文章包括标题、作者、赞数等信息,在关系型数据库中很容易构建一张表来存储这些信息,在 Redis 中可以使用 HASH 来存储每种信息以及其对应的值的映射。

Redis 没有关系型数据库中的表这一概念来将同种类型的数据存放在一起,而是使用命名空间的方式来实现这一功能。键名的前面部分存储命名空间,后面部分的内容存储 ID,通常使用 : 来进行分隔。例如下面的 HASH 的键名为 article:92617,其中 article 为命名空间,ID 为 92617。

点赞功能

当有用户为一篇文章点赞时,除了要对该文章的 votes 字段进行加 1 操作,还必须记录该用户已经对该文章进行了点赞,防止用户点赞次数超过 1。可以建立文章的已投票用户集合来进行记录。

为了节约内存,规定一篇文章发布满一周之后,就不能再对它进行投票,而文章的已投票集合也会被删除,可以为文章的已投票集合设置一个一周的过期时间就能实现这个规定。

对文章进行排序

为了按发布时间和点赞数进行排序,可以建立一个文章发布时间的有序集合和一个文章点赞数的有序集合。(下图中的 score 就是这里所说的点赞数;下面所示的有序集合分值并不直接是时间和点赞数,而是根据时间和点赞数间接计算出来的)

参考资料

  • Carlson J L. Redis in Action[J]. Media.johnwiley.com.au, 2013.

  • 黄健宏. Redis 设计与实现 [M]. 机械工业出版社, 2014.

  • REDIS IN ACTION

  • Skip Lists: Done Right

  • 论述 Redis 和 Memcached 的差异

  • Redis 3.0 中文版- 分片

  • Redis 应用场景

  • Using Redis as an LRU cache

  • 出自以下公众号

【End】

查看更多面试题内容,请访问《Java最常见200+面试题全解析》,它包含的模块有:

  • Java、JVM 最常见面试题解析

  • Spring、Spring MVC、MyBatis、Hibernate 面试题解析

  • MySQL、Redis 面试题解析

  • RabbitMQ、Kafka、Zookeeper 面试解析

  • 微服务 Spring Boot、Spring Cloud 面试解析

扫描下面二维码付费阅读

关注下方二维码,订阅更多精彩内容。

转发朋友圈,是对我最大的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/546622.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

八、华为鸿蒙HarmonyOS应用开发之Java UI框架、常用TextField组件使用

一、TextField组件 二、TextField组件实例测试 1.新建基于empty ability(Java)手机应用程序的TextField工程。运行出现如下结果 2.在resources->zh.element文件夹下string.json文件修改代码如下: {"string": [{"name": "entry_MainAbility&qu…

面试题:彻底搞懂 Cookie 和 Session

我在做面试官的时候&#xff0c;曾经问过很多朋友这个问题&#xff1a; Cookie 和 Session 有什么区别呢&#xff1f;大部分的面试者应该都可以说上一两句&#xff0c;比如&#xff1a;什么是 Cookie&#xff1f;什么是 Session&#xff1f;两者的区别等。但如果再往深入探讨的…

局域网内Windows允许其他电脑指定IP访问本地mysql-8.0.23数据库

第一步:用ping命令测试两台电脑是否连通 如果两台电脑是连通的请转到第二步,如果是非连通的请进行如下操作: 1、进入控制面板,打开Windows Defender 防火墙,点击高级设置(本人用的是Windows10,其他Windows版本操作类似) 2、在新弹出的页面中点击入站规则,在入站规则中…

经典面试题:聊一聊垃圾回收算法

关于垃圾回收算法的这道面试题&#xff0c;几乎是所有 3 年以上的 Java 面试中必问的题目&#xff0c;甚至有些好一点的公司会在校招时问到面试者。那么本文就系统的讲一下垃圾回收的算法&#xff0c;和 Hotspot 虚拟机执行垃圾回收的一些实现细节&#xff0c;比如安全点和安全…

九、华为鸿蒙HarmonyOS应用开发之Java UI框架、常用Image组件使用

一、Image 二、Image组件实例测试 1.新建基于empty ability(Java)手机应用程序的ImageTest工程。运行出现如下结果 2.在Project窗口,打开“entry > src > main > resources > base > media”,添加4个图片至media文件夹下,以“pic1.jpg”、“pic2.jpg”、…

阿里面试,我挂在了第四轮……

可能每个技术人都有个阿里梦&#xff0c;我也不例外。最近准备跳槽&#xff0c;前一阵子在准备各种面试&#xff0c;也面了几个大厂&#xff0c;包括阿里。是的&#xff0c;最后我挂在了第四轮。这篇文章来总结一下我在阿里四轮的面试经历&#xff0c;希望能对读者有所启发。阿…

基于IP-PBX的VoIP系统解决方案

基于IP-PBX的VoIP系统解决方案目前&#xff0c;众多企业随着业务的扩张&#xff0c;开设了大量的分支机构&#xff0c;这样企业总分支机构以及分支机构之间的语音沟通是非常频繁&#xff0c;企业长途电话费用是企业经营成本中的一项巨大开支。现在互联网已非常普及&#xff0c;…

面试官:聊一下二分法

来源&#xff1a;cnblogs.com/luoxn28/p/5767571.html1、二分查找二分查找是一个基础的算法&#xff0c;也是面试中常考的一个知识点。二分查找就是将查找的键和子数组的中间键作比较&#xff0c;如果被查找的键小于中间键&#xff0c;就在左子数组继续查找&#xff1b;如果大于…

Delphi利用Windows GDI实现文字倾斜

2019独角兽企业重金招聘Python工程师标准>>> procedure TForm1.FormPaint(Sender: TObject);var FLogFont: tagLogFontW; hTempFont, hPrevFont: HFONT; //字体句柄 hTempDC: HDC; //设备描述表或图形设备句柄 TempString: string; //输出的文字begin FLogFont…

面试干货 | Java 能否自定义一个类叫 java.lang.System?

本文由读者 apdoer 投稿&#xff0c;apdoer 是一个极具钻研精神的 Java 猿&#xff0c;技术牛X头发茂盛! 博客地址&#xff1a;https://blog.csdn.net/m0_43452671缘起&#xff1a;一个面试题最近在上下班地铁刷博客,无意刷到一个面试题,号称很多程序员的烈士公墓&#xff1a;j…

mysql 数据库文件导入和导出、远程上传和下载数据库

1.打开数据库操作软件:Navicat Premium 15 中文版,登录测试连接! 2.打开本地mysql 数据库,新建数据库的名字必须和要导入的数据库名字一致。字符集和排 序规则按下图设置即可。

经典面试题 | 讲一下垃圾回收器都有哪些?

垃圾回收器有哪些&#xff1f;是一个高频的面试题&#xff0c;那本文就详细来解答这个问题。因为不同的厂商&#xff08;IBM、Oracle&#xff09;&#xff0c;实现的垃圾回收器各不相同&#xff0c;而本文要讨论的是 Oracle 的 HotSpot 虚拟机所使用的垃圾回收器。常用垃圾回收…

十、华为鸿蒙HarmonyOS应用开发之Java UI框架、常用TabList组件使用

一、TabList和Tab 二、TabList组件实例测试 1.新建基于empty ability(Java

dotConnect for Oracle控件免费下载及使用方法

原文来自龙博方案网http://www.fanganwang.com/product/1330转载请注明出处dotConnect for Oracle完全基于ADO.NET方法&#xff0c;因此您完全可以采用标准ADO.NET数据提供的方法来使用它。是一款为Microsoft .NET Framework提供直接Oracle数据库连接的数据发生器控件。 具体功…

面试官:谈谈数据库连接池的原理

来源&#xff1a;https://dwz.cn/oUF6pKOW这次我们采取技术演进的方式来谈谈数据库连接池的技术出现过程及其原理&#xff0c;以及当下最流行的开源数据库连接池jar包。一、早期我们怎么进行数据库操作1、原理一般来说&#xff0c;Java应用程序访问数据库的过程是&#xff1a;①…

php调用twitter api

今天做了一个关于调用twitter api来同步twitter信息到自己网站的功能&#xff0c;虽然是比较简单的功能&#xff0c;着实花费了我不少时间。网上有很多关于twitter api调用的方法&#xff0c;我试了几个都没有成功&#xff0c;貌似需要Oauth验证&#xff0c;这个跟微信开发类似…

8种常见SQL错误用法,你犯过几个?

来源&#xff1a;https://yq.aliyun.com/articles/72501高考和端午小长假一溜烟的功夫就全过完了&#xff0c;新的一周&#xff0c;让我们迎着清晨的阳光&#xff0c;继续前行。1、LIMIT 语句分页查询是最常用的场景之一&#xff0c;但也通常也是最容易出问题的地方。比如对于下…

51单片机 16*64LED单红点阵屏驱动测试,上位机改字软件免费版

public.h #ifndef __PUBLIC_H__ #define __PUBLIC_H__#include "STC12C5A60S2.h" #include <intrins.h> #include <string.h>//包含memset函数#define UCHAR unsigned char #define UINT unsigned int #define TRUE 1 #define FALSE 0#define LEDON 0…

cocos2dx基础篇(2)——Win32移植到Android

【安装工具】JDKEclipse 或直接下一个 ADT集成开发工具SDKNDK9rADTCDT安装方法自行百度。【正文】1、由 Cocos2D-X 和 VS2010 环境配置——1 中提到的python方法&#xff0c;创建新项目。然后将你开发好的win项目相应的文件Classes和Resources文件夹里的东西分别拷贝到刚创建的…

HR一般不会告诉你的八大真相

我们都是经历过招聘面试的&#xff0c;HR那种微笑很深奥很捉摸不透想必你也见过&#xff0c;但是就是猜不透是什么意思对吧&#xff1f;那么&#xff0c;就赶紧来看看这些HR一般不会告诉你的真相吧!1.求职实际上是一个难以公平的被拒绝过程公平的环境下求职?从HR的角度来说&am…