redis的学习(四)
13. 渐进式遍历
通过渐进式遍历能够获取当前所有的key,又不会讲当前的服务器卡死。不是一个命令将所有的key获取,而是每执行一次命令,只获取到其中的一部分。所以想要获取到所有的key就需要多次遍历,即化整为零的思想。
渐进式遍历其实是一组命令,其命令的使用方法是一样的。代表命令式scan。


化整为零的渐进式遍历:

count这里的数值不一定每一次都是一样的,渐进式遍历在遍历过程中,不会在服务器中存储任何的状态信息,且此处的遍历是随时可以终止的,不会对服务器产生任何的副作用。
渐进性遍历scan虽然解决了阻塞的问题,但如果在遍历期间键有所变化(增加、修改、删 除),可能导致遍历时键的重复遍历或者遗漏。在遍历的时候进行修改/新增/删除,会导致迭代器失效。
14. 数据库管理
redis中的database是现成的,用户不能创建新的,也不能删除已有的数据库。redis默认提供了16个数据库0~15,这些数据库中的数据是隔离的,默认使用的数据库是0号。
select dbIndex,切换数据库。

dbsize:获取当前库中存在的key的个数。
15. redis客户端介绍
工作中,是使用redis的api,来实现定制化的redis客户端程序,进一步操作redis服务器。即使用程序来操作服务器。
关于编写一个自定义的redis客户端:
主要是因为能够从redis官网获取redis服务器应用层的协议如下:

resp协议:
优点:1、简单好实现;2、快速进行解析;3、肉眼可读。
传输层这里基于tcp,但是和tcp没有进行强耦合。请求和响应之间是一问一答的模式机制。


simple string只能用来传输简单的文本,bulk string可以传输二进制数据。因此redis客户端服务器的工作就是:1、按照上述的格式,构造出字符串,往socket中写入。2、从socket中读取字符串,按照上述格式进行解析。
java生态中,开发代码高度依赖windows(idea),所以需要通过云服务器的外网ip来访问到linux服务器。redis在云服务器上的端口是6379,一般是被云服务器的防火墙保护起来的。redis的端口不能直接在防火墙上放开。
不能开发redis端口,邮箱能够通过外网访问方案:
1、直接让java程序也在linux上运行,即将java代码打包成可执行的jar包,然后将jar包拷贝到linux服务器上执行。
2、配置ssh端口转发,把云服务器的redis端口映射到本地主机。
下面描述云服务器的端口映射到本地主机:
windows(本地主机)的终端(类似于xsehll)通过ssh协议访问到云服务器。ssh既是协议也是程序,默认走22端口。ssh其中一个功能是能够支持端口转发,通过走ssh的22端口来传递去其他端口的数据信息。
即使用本地主机访问云服务器的6379端口,本地先构造一个ssh数据报,将访问redis的请求放到数据报里面,这个数据报会通过22端口发往服务器,服务器的ssh服务器程序就能解析出上述的数据报,将其交给6379端口的程序。一个linux主机上,存在很多的服务器,ssh肯呢个需要给多个端口传递数据,此时为了区分不同的端口,往往会把服务器的端口在本地用另外一个端口来表示。
所以把服务器的6379端口使用ssh进行端口映射,映射到本地8888端口。则本地的客户端程序访问127.0.0.1:8888,就相当于访问云服务器上的6379。
下图ssh端口转发隧道:

当ssh连接上之后端口转发才有效,把ssh连接断开之后,端口转发自然就消失了。 连接完成之后使用netstat命令来查看本地的8888端口监听情况。

15.1 创建java项目
1、使用jedis来操作redis
引入依赖:
</dependency> <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.2</version> </dependency>
public class RedisDemo {public static void main(String[] args) {//连接redis服务器JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888");// 后续记得cloas,只是放回到池里,并不是直接关闭tcp连接try(Jedis jedis = jedisPool.getResource()){String pong = jedis.ping();System.out.println(pong);}}
}
运行结果如下:

程序运行成功除了ssh映射配置成功之外,还有就是最开始安装redis服务器的时候要配置绑定的ip以及关闭保护模式。
15.2 get和set
public class RedisDemo {public static void main(String[] args) {//连接redis服务器JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888");// 后续记得cloas,只是放回到池里,并不是直接关闭tcp连接try(Jedis jedis = jedisPool.getResource()){
// String pong = jedis.ping();
// System.out.println(pong);test1(jedis);}}public static void test1(Jedis jedis){System.out.println("get和set的使用");//清空数据库
// jedis.flushAll();jedis.set("k11","11");jedis.set("k12","12");String value = jedis.get("k11");System.out.println("value="+value);}
}
运行结果:

15.2 exists 和 del
del可以删除多个key,以变⻓参数列表的⽅式体现.返回值是实际删除的key的个数.
boolean ret = jedis.exists("key1");System.out.println(ret);n = jedis.del("key2", "key3");System.out.println(n);
15.3 keys的使用
public static void test3(Jedis jedis) {jedis.set("key1", "value1");jedis.set("key2", "value2");jedis.set("key3", "value3");jedis.set("myKey", "value4");Set<String> keys = jedis.keys("*");System.out.println(keys);}
运行结果如下:

15.4 expire和ttl
public static void test4(Jedis jedis) {System.out.println("expire和ttl的使用");jedis.set("key1", "value1");String type = jedis.type("key")jedis.expire("k1",10);long time = jedis.ttl("key1");}
15.5 type
private static void testType(Jedis jedis) {jedis.set("key1", "value");System.out.println(jedis.type("key1"));jedis.lpush("key2", "a", "b", "c");System.out.println(jedis.type("key2"));jedis.hset("key3", "name", "zhangsan");System.out.println(jedis.type("key3"));jedis.sadd("key4", "111", "222", "333");System.out.println(jedis.type("key4"));jedis.zadd("key5", 1, "aaa");System.out.println(jedis.type("key5"));
}
15.6 string相关的命令
System.out.println("mget 和 mset");
jedis.flushAll();
jedis.mset("key1", "111", "key2", "222", "key3", "333");
List<String> values = jedis.mget("key1", "key2", "key100", "key3");
//返回的结果只和传递的参数有关,没有也会返回null
System.out.println("values: " + values);System.out.println("getrange 和 setrange");
jedis.flushAll();
jedis.set("key", "abcdefghijk");
String result = jedis.getrange("key", 2, 5);
System.out.println("result: " + result);
jedis.setrange("key", 2, "xyz");
String value = jedis.get("key");
System.out.println("value: " + value);System.out.println("append");
jedis.flushAll();
jedis.set("key", "abcdef");
jedis.append("key", "ghij");
String value = jedis.get("key");
System.out.println("value: " + value);System.out.println("incr 和 decr");
jedis.flushAll();
jedis.set("key", "100");
long result = jedis.incr("key");
System.out.println("result: " + result);
result = jedis.decr("key");
System.out.println("result: " + result);
value = jedis.get("key");
System.out.println("value: " + value);
15.7 list相关的命令
System.out.println("lpush 和 lrange");
jedis.flushAll();
jedis.lpush("key", "111", "222", "333");
List<String> result = jedis.lrange("key", 0, -1);
System.out.println(result);System.out.println("rpush");
jedis.flushAll();
jedis.rpush("key", "111", "222", "333");
List<String> result = jedis.lrange("key", 0, -1);
System.out.println("result: " + result);System.out.println("lpop");
jedis.flushAll();
jedis.rpush("key", "111", "222", "333");
String result = jedis.lpop("key");
System.out.println("result: " + result);
result = jedis.lpop("key");
System.out.println("result: " + result);
result = jedis.lpop("key");
System.out.println("result: " + result);
result = jedis.lpop("key");
System.out.println("result: " + result);System.out.println("blpop");
jedis.flushAll();
// 返回结果是一个 "二元组", 一个是从哪个 key 对应的list中删除的, 一个是删除的元素是什么.
List<String> results = jedis.blpop(100, "key");
System.out.println("results[0]: " + results.get(0));
System.out.println("results[1]: " + results.get(1));System.out.println("llen");
jedis.flushAll();
jedis.rpush("key", "111", "222", "333");
long len = jedis.llen("key");
System.out.println("len: " + len);
15.8 关于set相关的命令
System.out.println("sadd 和 smembers");jedis.flushAll();jedis.sadd("key", "111", "222", "333");Set<String> result = jedis.smembers("key");System.out.println("result: " + result);System.out.println("sismember");jedis.flushAll();jedis.sadd("key", "111", "222", "333");boolean result = jedis.sismember("key", "100");System.out.println("result: " + result);System.out.println("scard");jedis.flushAll();jedis.sadd("key", "111", "222", "333");long result = jedis.scard("key");System.out.println("result: " + result);System.out.println("spop");jedis.flushAll();jedis.sadd("key", "111", "222", "333", "444", "555");String result = jedis.spop("key");System.out.println("result: " + result);System.out.println("sinter");jedis.flushAll();jedis.sadd("key", "111", "222", "333");jedis.sadd("key2", "111", "222", "444");Set<String> result = jedis.sinter("key", "key2");System.out.println("result: " + result);System.out.println("sinterstore");jedis.flushAll();jedis.sadd("key", "111", "222", "333");jedis.sadd("key2", "111", "222", "444");long len = jedis.sinterstore("key3", "key", "key2");System.out.println("len: " + len);Set<String> result = jedis.smembers("key3");System.out.println("result: " + result);
15.9 关于hash的指令
System.out.println("hset 和 hget");jedis.flushAll();jedis.hset("key", "f1", "111");Map<String, String> fields = new HashMap<>();fields.put("f2", "222");fields.put("f3", "333");jedis.hset("key", fields);String result = jedis.hget("key", "f1");System.out.println("result: " + result);result = jedis.hget("key", "f2");System.out.println("result: " + result);result = jedis.hget("key", "f100");System.out.println("result: " + result);System.out.println("hexists");jedis.flushAll();jedis.hset("key", "f1", "111");jedis.hset("key", "f2", "111");jedis.hset("key", "f3", "111");boolean result = jedis.hexists("key", "f1");System.out.println("result: " + result);result = jedis.hexists("key", "f100");System.out.println("result: " + result);System.out.println("hdel");jedis.flushAll();jedis.hset("key", "f1", "111");jedis.hset("key", "f2", "111");jedis.hset("key", "f3", "111");long result = jedis.hdel("key", "f1", "f2");System.out.println("result: " + result);boolean exists = jedis.hexists("key", "f1");System.out.println("exists: " + exists);exists = jedis.hexists("key", "f2");System.out.println("exists: " + exists);System.out.println("hkeys 和 hvals");jedis.flushAll();jedis.hset("key", "f1", "111");jedis.hset("key", "f2", "111");jedis.hset("key", "f3", "111");Set<String> fields = jedis.hkeys("key");List<String> vals = jedis.hvals("key");System.out.println("fields: " + fields);System.out.println("vals: " + vals);System.out.println("hmget 和 hmset");jedis.flushAll();Map<String, String> map = new HashMap<>();map.put("f1", "111");map.put("f2", "222");map.put("f3", "333");jedis.hmset("key", map);List<String> values = jedis.hmget("key", "f2", "f1", "f3");System.out.println("values: " + values);
15.10 关于zset的指令
System.out.println("zadd 和 zrange");jedis.flushAll();jedis.zadd("key", 10, "zhangsan");Map<String, Double> map = new HashMap<>();map.put("lisi", 20.0);map.put("wangwu", 30.0);jedis.zadd("key", map);List<String> members = jedis.zrange("key", 0, -1);System.out.println("members: " + members);List<Tuple> membersWithScore = jedis.zrangeWithScores("key", 0, -1);System.out.println("membersWithScore: " + membersWithScore);String member = membersWithScore.get(0).getElement();double score = membersWithScore.get(0).getScore();System.out.println("member: " + member + ", score: " + score);System.out.println("zcard");jedis.flushAll();jedis.zadd("key", 10, "zhangsan");jedis.zadd("key", 20, "lisi");jedis.zadd("key", 30, "wangwu");long len = jedis.zcard("key");System.out.println("len: " + len);System.out.println("zrem");jedis.flushAll();jedis.zadd("key", 10, "zhangsan");jedis.zadd("key", 20, "lisi");jedis.zadd("key", 30, "wangwu");long n = jedis.zrem("key", "zhangsan", "lisi");System.out.println("n: " + n);List<Tuple> result = jedis.zrangeWithScores("key", 0, -1);System.out.println("result: " + result);System.out.println("zscore");jedis.flushAll();jedis.zadd("key", 10, "zhangsan");jedis.zadd("key", 20, "lisi");jedis.zadd("key", 30, "wangwu");Double score = jedis.zscore("key", "zhangsan2");System.out.println("score: " + score);System.out.println("zrank");jedis.flushAll();jedis.zadd("key", 10, "zhangsan");jedis.zadd("key", 20, "lisi");jedis.zadd("key", 30, "wangwu");Long rank = jedis.zrank("key", "zhangsan2");System.out.println("rank: " + rank);
jedis库的本质就是针对各种redis指令进行了包装,调用某个方法,就相当于在redis客户端中输入对应的命令。
2、在spring中操作redis
配置.yml文件,添加相关依赖。


// 后续 redis 测试的各种方法, 都通过这个 Controller 提供的 http 接口来触发.
@RestController
public class MyController {@Autowiredprivate StringRedisTemplate redisTemplate;//这里spring中是通过stringredisTemplate来操作redis//stringredisTemplate是redisTemplate的子类,专门来处理文本数据@GetMapping("/testString")@ResponseBodypublic String testString() {redisTemplate.execute((RedisConnection connection) -> {// execute 要求回调方法中必须写 return 语句. 返回个东西.// 这个回调返回的对象, 就会作为 execute 本身的返回值.connection.flushAll();return null;});redisTemplate.opsForValue().set("key", "111");redisTemplate.opsForValue().set("key2", "222");redisTemplate.opsForValue().set("key3", "333");String value = redisTemplate.opsForValue().get("key");System.out.println("value: " + value);return "OK";}@GetMapping("/testList")@ResponseBodypublic String testList() {// 先清除之前的数据.//使用lambda表达式来写函数式接口redisTemplate.execute((RedisConnection connection) -> {// execute 要求回调方法中必须写 return 语句. 返回个东西.// 这个回调返回的对象, 就会作为 execute 本身的返回值.//RedisConnection,代表了redis连接,对标jedisconnection.flushAll();return null;});redisTemplate.opsForList().leftPush("key", "111");redisTemplate.opsForList().leftPush("key", "222");redisTemplate.opsForList().leftPush("key", "333");String value = redisTemplate.opsForList().rightPop("key");System.out.println("value: " + value);value = redisTemplate.opsForList().rightPop("key");System.out.println("value: " + value);value = redisTemplate.opsForList().rightPop("key");System.out.println("value: " + value);return "OK";}@GetMapping("/testSet")@ResponseBodypublic String testSet() {redisTemplate.execute((RedisConnection connection) -> {connection.flushAll();return null;});redisTemplate.opsForSet().add("key", "111", "222", "333");Set<String> result = redisTemplate.opsForSet().members("key");System.out.println("result: " + result);Boolean exists = redisTemplate.opsForSet().isMember("key", "111");System.out.println("exists: " + exists);Long count = redisTemplate.opsForSet().size("key");System.out.println("count: " + count);redisTemplate.opsForSet().remove("key", "111", "222");result = redisTemplate.opsForSet().members("key");System.out.println("result: " + result);return "OK";}@GetMapping("/testHash")@ResponseBodypublic String testHash() {redisTemplate.execute((RedisConnection connection) -> {connection.flushAll();return null;});redisTemplate.opsForHash().put("key", "f1", "111");redisTemplate.opsForHash().put("key", "f2", "222");redisTemplate.opsForHash().put("key", "f3", "333");String value = (String) redisTemplate.opsForHash().get("key", "f1");System.out.println("value: " + value);Boolean exists = redisTemplate.opsForHash().hasKey("key", "f1");System.out.println("exists: " + exists);redisTemplate.opsForHash().delete("key", "f1", "f2");Long size = redisTemplate.opsForHash().size("key");System.out.println("size: " + size);return "OK";}@GetMapping("/testZSet")@ResponseBodypublic String testZSet() {redisTemplate.execute((RedisConnection connection) -> {connection.flushAll();return null;});redisTemplate.opsForZSet().add("key", "zhangsan", 10);redisTemplate.opsForZSet().add("key", "lisi", 20);redisTemplate.opsForZSet().add("key", "wangwu", 30);Set<String> members = redisTemplate.opsForZSet().range("key", 0, -1);System.out.println("members: " + members);Set<ZSetOperations.TypedTuple<String>> membersWithScore = redisTemplate.opsForZSet().rangeWithScores("key", 0, -1);System.out.println("membersWithScore: " + membersWithScore);Double score = redisTemplate.opsForZSet().score("key", "zhangsan");System.out.println("score: " + score);redisTemplate.opsForZSet().remove("key", "zhangsan");Long size = redisTemplate.opsForZSet().size("key");System.out.println("size: " + size);Long rank = redisTemplate.opsForZSet().rank("key", "lisi");System.out.println("rank: " + rank);return "OK";}
}
ps:redis的简单学习就到这里了,谢谢观看。
相关文章:
redis的学习(四)
13. 渐进式遍历 通过渐进式遍历能够获取当前所有的key,又不会讲当前的服务器卡死。不是一个命令将所有的key获取,而是每执行一次命令,只获取到其中的一部分。所以想要获取到所有的key就需要多次遍历,即化整为零的思想。 渐进式遍历…...
C# winform 多线程 UI更新数据 报错:无法访问已释放的对象。
System.ObjectDisposedException HResult0x80131622 Message无法访问已释放的对象。 ObjectDisposed_ObjectName_Name SourceSystem.Windows.Forms StackTrace: at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, …...
error: linker `link.exe` not found
开始学习rust,安装好rust的环境,开始从hello world开始,结果用在win10环境下,使用vs code或cmd窗口编译rust报错: PS E:\study_codes\rust-demo\chart01> rustc hello.rs error: linker link.exe not found| note:…...
Vue.js组件开发-如何使用moment.js
在Vue.js组件开发中,需要处理日期和时间,moment.js 是一个非常有用的库。moment.js 提供了丰富的API来解析、验证、操作和显示日期和时间。 步骤: 1. 安装moment.js 首先,需要通过npm或yarn安装moment.js。在项目根目录下运行以…...
Linux第二课:LinuxC高级 学习记录day01
0、大纲 0.1、Linux 软件安装,用户管理,进程管理,shell 命令,硬链接和软连接,解压和压缩,功能性语句,结构性语句,分文件,make工具,shell脚本 0.2、C高级 …...
《DOM NodeList》
《DOM NodeList》 介绍 DOM(文档对象模型)是HTML和XML文档的编程接口,它允许开发者在JavaScript等编程语言中操作文档的结构、样式和内容。在DOM中,NodeList是一个重要的接口,它表示一个包含节点(如元素、…...
Nginx代理同域名前后端分离项目的完整步骤
前后端分离项目,前后端共用一个域名。通过域名后的 url 前缀来区别前后端项目。 以 vue php 项目为例。直接上 server 模块的 nginx 配置。 server{ listen 80; #listen [::]:80 default_server ipv6onlyon; server_name demo.com;#二配置项目域名 index index.ht…...
uniapp页面高度设置(铺满可视区域、顶部状态栏高度、底部导航栏高度)
这里说几种在uniapp开发中,关于页面设置高度的几种情况。宽度就不说了哈,宽度设置百分比都会生效。 首先我们要知道平时开发中,如果说没在uniapp做特殊处理,即正常情况下,所有的页面(.vue文件)中都是没有高度的(和vue一样),也就是说给最外层的的view标签设置高度为1…...
解锁 RAG 技术:从原理、论文研读走向实战应用RAG
亲爱的小伙伴们😘,在求知的漫漫旅途中,若你对深度学习的奥秘、Java 与 Python 的奇妙世界,亦或是读研论文的撰写攻略有所探寻🧐,那不妨给我一个小小的关注吧🥰。我会精心筹备,在未来…...
HTML5实现好看的中秋节网页源码
HTML5实现好看的中秋节网页源码 前言一、设计来源1.1 网站首页界面1.2 登录注册界面1.3 节日由来界面1.4 节日习俗界面1.5 节日文化界面1.6 节日美食界面1.7 节日故事界面1.8 节日民谣界面1.9 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看…...
数字孪生笔记 1 工业数字孪生的意义
什么是工业数字孪生? 很多在做这个工作研究的同学最开始都想问的一个问题。到底什么才是数字孪生?我在五年前做数字孪生的时候也在思考这个问题。五年时间从数字孪生兴起,到元宇宙爆发,再到数字孪生和元宇宙没人提起,…...
013:深度学习之神经网络
本文为合集收录,欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请参考这里。 深度学习是机器学习中重要的一个学科分支,它的特点就在于需要构建多层且“深度”的神经网络。 人们在探索人工智能初期,就曾设想构建一个用数学方式…...
计算机网络(四)网络层
4.1、网络层概述 简介 网络层的主要任务是实现网络互连,进而实现数据包在各网络之间的传输 这些异构型网络N1~N7如果只是需要各自内部通信,他们只要实现各自的物理层和数据链路层即可 但是如果要将这些异构型网络互连起来,形成一个更大的互…...
【ArcGIS微课1000例】0138:ArcGIS栅格数据每个像元值转为Excel文本进行统计分析、做图表
本文讲述在ArcGIS中,以globeland30数据为例,将栅格数据每个像元值转为Excel文本,便于在Excel中进行统计分析。 文章目录 一、加载globeland30数据二、栅格转点三、像元值提取至点四、Excel打开一、加载globeland30数据 打开配套实验数据包中的0138.rar中的tif格式栅格土地覆…...
Linux 中统计进程的线程数 | 查看进程的线程
注:本文为 “Linux 线程” 相关文章合辑。 在 Linux 中统计一个进程的线程数 作者:Dan Nanni 译者: LCTT struggling | 2015-09-17 10:29 在 Linux 中一个程序在运行时会派生出多个线程。检查每个进程的线程数,有以下几种方法可…...
【深度学习 】训练过程中loss出现nan
[toc]【深度学习 】训练过程中loss出现nan 训练过程中loss出现nan 在深度学习中,loss 出现 NaN 通常是由数值不稳定或计算错误引起的。 1. 学习率过高 原因: 学习率过大可能导致权重更新幅度过大,引发数值不稳定。 解决方法: 降低学习率,…...
Linux - 什么是线程和线程的操作
线程概念 什么是线程: 线程(Thread)是操作系统能够进行运算调度的最小单位. 它被包含在进程之中, 是进程中的实际运作单位. 一个进程可以包含多个线程. 进程 : 线程 1 : n (n > 1). 进程是系统分配资源的基本单位. 线程则是系统调度的基本单位. 在…...
windows及linux 安装 Yarn 4.x 版本
1. 确保系统环境准备 a. 安装 Node.js Yarn 依赖于 Node.js,所以需要先安装 Node.js。前往 Node.js 官网 下载并安装适合你的 Windows 版本的 Node.js(推荐 LTS 版本)。安装完成后,打开命令提示符(CMD)或 PowerShell,验证安装:node -v npm -v如果显示版本号,则表示安…...
如何设计一个 RPC 框架?需要考虑哪些点?
面试官:如何设计一个 RPC 框架?需要考虑哪些点? 设计一个远程过程调用(RPC)框架是一个复杂的系统工程,涉及多个方面的考虑。一个好的 RPC 框架应具备可扩展性、灵活性、易用性和高性能。下面是设计 RPC 框…...
初学stm32 --- DAC输出三角波和正弦波
输出三角波实验简要: 1,功能描述 通过DAC1通道1(PA4)输出三角波,然后通过DS100示波器查看波形 2,关闭通道1触发(即自动) TEN1位置0 3,关闭输出缓冲 BOFF1位置1 4,使用12位右对齐模式 将数字量写入DAC_…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
