Redis从简单使用到底层原理与分布式缓存

news2024/11/24 8:34:36

文章目录

  • ==[Redis参考手册](https://redis.io/docs/latest/commands/)==
  • 1 基础认识
    • 1.1 安装配置
    • 1.2 通用命令
    • 1.3 数据类型
      • 1.3.1 数据结构与内部编码
      • string
      • key的结构
      • hash
      • list
      • set
      • sorted_set
    • 1.4 单线程模型
  • 2 redis客户端
    • 2.1 RESP协议(Redis serialization protocol)
    • 2.2 基础案例
  • 3 分布式缓存 —— redis集群
    • 3.1 持久化
      • 3.1.1 RDB
      • 3.1.2 RDB底层原理
      • 3.1.3 AOF持久化
      • 3.1.4 AOF与RDB的对比
    • 3.2 Redis主从
      • 3.2.1 搭建主从集群
      • 3.2.2 数据同步原理
    • 3.3 Redis哨兵
        • Sentinel监控原理
        • 选择新的master
        • 如何实现故障转移
      • 3.3.1 搭建哨兵集群
      • 3.3.2 Redis客户端状态感知
    • 3.4 Redis分片集群
      • 3.4.1 搭建分片集群
      • 3.4.2 散列插槽
      • 3.4.3 集群伸缩
      • 3.4.4 故障转移
  • 4 多级缓存
    • 4.1 JVM进程缓存
    • 4.2 OpenResty
    • 4.3 缓存同步
      • 4.3.1 Canel
  • 5 Redis实践优化
    • 5.1 key的设计
    • 5.2 批处理优化
      • 5.2.1 集群模式下的批处理
    • 5.3 服务端优化
      • 5.3.1 持久化配置
      • 5.3.2 慢查询
      • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
      • 5.3.3 服务器安全配置
      • 5.3.4 内存配置
      • 5.3.5 集群相关问题
  • 6 Redis底层原理
    • 6.1 底层数据结构
      • 6.1.1 SDS动态数组
      • 6.1.2 Intset
      • 6.1.3 Dict
      • 6.1.4 ZipList
      • 6.1.5 QuickList
      • 6.1.5 SkipList
      • 6.1.6 RedisObject
    • 6.2 五种数据结构
      • 6.2.1 String
      • 6.2.2 List
      • 6.2.3 Set
      • 6.2.4 ZSet
      • 6.2.5 Hash
    • 6.3 Redis网络模型
      • 6.3.1 selecct
      • 6.3.2 poll
      • 6.3.3 epoll
      • 6.3.4 Redis网络模型
    • 6.4 Redis通信协议
  • 7 Redis实战
    • 7.1 短信登录
    • 7.2 商户查询缓存
      • 6.2.4 ZSet
      • 6.2.5 Hash
    • 6.3 Redis网络模型
      • 6.3.1 selecct
      • 6.3.2 poll
      • 6.3.3 epoll
      • 6.3.4 Redis网络模型
    • 6.4 Redis通信协议
  • 7 Redis实战
    • 7.1 短信登录
    • 7.2 商户查询缓存

Redis参考手册

1 基础认识

  • NoSQL与SQL

    image-20240425234137088

  • 特征

image-20240425234614363

1.1 安装配置

  • 安装:sudo apt install redis

  • 配置文件etc/redis/redis.conf

    bind 0.0.0.0 ::1    #将本地环回改为任意ip
    
    daemonize yes #守护进程启动
    
    requirepass 123123 #设置密码为123123
    
    protected-mode no   #开启后其他主机才能访问
    
    logfile "xxx.log"  #开启日志,并记录到xxx.log中
    

    配置完后重启服务器:service redis-sever restart

    查看运行状态:service redis-server status

  • 链接

    redis-cli
    
    #--raw 将二进制编码
    
  • 退出:quitctrl + d

1.2 通用命令

help @generic #查看通用命令文档 
  • 类型
    • key:字符串
    • value:字符串、哈希表、列表、集合…
  1. get
GET key
  1. set
SET key value
  1. exists
EXISTS key [key ...]	#判断多个key,返回key存在  的个数
  1. del
DEL key [key ...] #返回删除key的个数
  1. expire:设置过期时间
EXPIRE key [seconds]
PEXPIRE key [millisecond]
  1. ttl:(time to live)获取key的过期时间
TTL key   #返回-2表示key已经删除了
  • 过期策略

定期删除 与 惰性删除 相结合

  1. type : 查看key对应的value的值
redis> SET key1 "value"
"OK"
redis> LPUSH key2 "value"
(integer) 1
redis> SADD key3 "value"
(integer) 1
redis> TYPE key1
"string"
redis> TYPE key2
"list"
redis> TYPE key3
"set"
redis> 
  1. keys
KEYS pattern
  • pattern

    image-20240421224000208

  1. flushall:清除所有数据库中的key

  2. scan ——渐进式遍历

  3. select dbIndex —— 切换数据库

dbIndex范围为0-15

1.3 数据类型

1.3.1 数据结构与内部编码

  • raw:原始字符串(C语言中的字符数组)

  • embstr:对于短字符串的优化

  • ziplist:对于键值对少的时候,通过压缩列表进行优化

  • quicklist:从redis3.2开始用quicklist实现list

  • skiplist:跳表

image-20240422011248940

  • 查看实际编码方式

    OBJECT encoding key
    

string

  1. set
SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]

image-20240422020234175

  1. get

get只能查询字符串类型的value

  1. mget / mset

设置/获取多组键值对

  1. setnx / setex / psetex

不存在则设置/另外设置过期时间(单位s)/(单位ms)

  1. #将value视为整数,对其+-
    incr		
    incrby
    decr
    decrby
    incrbyfloat		#前面四个只能算整数,incrbyfloat可以算浮点数
    
  2. 函数例子效果
    appendappend key value追加fvalue
    getrangegetrange key start end截取value的[start, end]区间部分,负数下标表示倒数
    setrangesetrange key offset valueoffset表示从第几个开始
    strlenstrlen key获取value的长度(字符为单位),若不是string类型则报错

key的结构

  • 让redis像mysql一样存储
  • key:数据库:表
  • value:{字段:值, 字段:值...}

image-20240426144736318

hash

image-20240426145202610

list

image-20240426150022647

set

image-20240426151000576

sorted_set

  • 默认按score升序排列,在Z后面加上REV倒序排列

image-20240426151322606

1.4 单线程模型

redis虽然是单线程模型,为什么效率却这么高

  1. 访问内存,MySQL则多是访问硬盘
  2. 核心功能简单
  3. 单线程模型,避免了多线程带来的开销
  4. 底层使用epoll

2 redis客户端

  • redis自定义应用层协议

2.1 RESP协议(Redis serialization protocol)

2.2 基础案例

#include <sw/redis++/redis++.h>

using namespace sw::redis;

try {
    // Create an Redis object, which is movable but NOT copyable.
    auto redis = Redis("tcp://127.0.0.1:6379");

    // ***** STRING commands *****

    redis.set("key", "val");
    auto val = redis.get("key");    // val is of type OptionalString. See 'API Reference' section for details.
    if (val) {
        // Dereference val to get the returned value of std::string type.
        std::cout << *val << std::endl;
    }   // else key doesn't exist.

    // ***** LIST commands *****

    // std::vector<std::string> to Redis LIST.
    std::vector<std::string> vec = {"a", "b", "c"};
    redis.rpush("list", vec.begin(), vec.end());

    // std::initializer_list to Redis LIST.
    redis.rpush("list", {"a", "b", "c"});

    // Redis LIST to std::vector<std::string>.
    vec.clear();
    redis.lrange("list", 0, -1, std::back_inserter(vec));

    // ***** HASH commands *****

    redis.hset("hash", "field", "val");

    // Another way to do the same job.
    redis.hset("hash", std::make_pair("field", "val"));

    // std::unordered_map<std::string, std::string> to Redis HASH.
    std::unordered_map<std::string, std::string> m = {
        {"field1", "val1"},
        {"field2", "val2"}
    };
    redis.hmset("hash", m.begin(), m.end());

    // Redis HASH to std::unordered_map<std::string, std::string>.
    m.clear();
    redis.hgetall("hash", std::inserter(m, m.begin()));

    // Get value only.
    // NOTE: since field might NOT exist, so we need to parse it to OptionalString.
    std::vector<OptionalString> vals;
    redis.hmget("hash", {"field1", "field2"}, std::back_inserter(vals));

    // ***** SET commands *****

    redis.sadd("set", "m1");

    // std::unordered_set<std::string> to Redis SET.
    std::unordered_set<std::string> set = {"m2", "m3"};
    redis.sadd("set", set.begin(), set.end());

    // std::initializer_list to Redis SET.
    redis.sadd("set", {"m2", "m3"});

    // Redis SET to std::unordered_set<std::string>.
    set.clear();
    redis.smembers("set", std::inserter(set, set.begin()));

    if (redis.sismember("set", "m1")) {
        std::cout << "m1 exists" << std::endl;
    }   // else NOT exist.

    // ***** SORTED SET commands *****

    redis.zadd("sorted_set", "m1", 1.3);

    // std::unordered_map<std::string, double> to Redis SORTED SET.
    std::unordered_map<std::string, double> scores = {
        {"m2", 2.3},
        {"m3", 4.5}
    };
    redis.zadd("sorted_set", scores.begin(), scores.end());

    // Redis SORTED SET to std::vector<std::pair<std::string, double>>.
    // NOTE: The return results of zrangebyscore are ordered, if you save the results
    // in to `std::unordered_map<std::string, double>`, you'll lose the order.
    std::vector<std::pair<std::string, double>> zset_result;
    redis.zrangebyscore("sorted_set",
            UnboundedInterval<double>{},            // (-inf, +inf)
            std::back_inserter(zset_result));

    // Only get member names:
    // pass an inserter of std::vector<std::string> type as output parameter.
    std::vector<std::string> without_score;
    redis.zrangebyscore("sorted_set",
            BoundedInterval<double>(1.5, 3.4, BoundType::CLOSED),   // [1.5, 3.4]
            std::back_inserter(without_score));

    // Get both member names and scores:
    // pass an back_inserter of std::vector<std::pair<std::string, double>> as output parameter.
    std::vector<std::pair<std::string, double>> with_score;
    redis.zrangebyscore("sorted_set",
            BoundedInterval<double>(1.5, 3.4, BoundType::LEFT_OPEN),    // (1.5, 3.4]
            std::back_inserter(with_score));

    // ***** SCRIPTING commands *****

    // Script returns a single element.
    auto num = redis.eval<long long>("return 1", {}, {});

    // Script returns an array of elements.
    std::vector<std::string> nums;
    redis.eval("return {ARGV[1], ARGV[2]}", {}, {"1", "2"}, std::back_inserter(nums));

    // mset with TTL
    auto mset_with_ttl_script = R"(
        local len = #KEYS
        if (len == 0 or len + 1 ~= #ARGV) then return 0 end
        local ttl = tonumber(ARGV[len + 1])
        if (not ttl or ttl <= 0) then return 0 end
        for i = 1, len do redis.call("SET", KEYS[i], ARGV[i], "EX", ttl) end
        return 1
    )";

    // Set multiple key-value pairs with TTL of 60 seconds.
    auto keys = {"key1", "key2", "key3"};
    std::vector<std::string> args = {"val1", "val2", "val3", "60"};
    redis.eval<long long>(mset_with_ttl_script, keys.begin(), keys.end(), args.begin(), args.end());

    // ***** Pipeline *****

    // Create a pipeline.
    auto pipe = redis.pipeline();

    // Send mulitple commands and get all replies.
    auto pipe_replies = pipe.set("key", "value")
                            .get("key")
                            .rename("key", "new-key")
                            .rpush("list", {"a", "b", "c"})
                            .lrange("list", 0, -1)
                            .exec();

    // Parse reply with reply type and index.
    auto set_cmd_result = pipe_replies.get<bool>(0);

    auto get_cmd_result = pipe_replies.get<OptionalString>(1);

    // rename command result
    pipe_replies.get<void>(2);

    auto rpush_cmd_result = pipe_replies.get<long long>(3);

    std::vector<std::string> lrange_cmd_result;
    pipe_replies.get(4, back_inserter(lrange_cmd_result));

    // ***** Transaction *****

    // Create a transaction.
    auto tx = redis.transaction();

    // Run multiple commands in a transaction, and get all replies.
    auto tx_replies = tx.incr("num0")
                        .incr("num1")
                        .mget({"num0", "num1"})
                        .exec();

    // Parse reply with reply type and index.
    auto incr_result0 = tx_replies.get<long long>(0);

    auto incr_result1 = tx_replies.get<long long>(1);

    std::vector<OptionalString> mget_cmd_result;
    tx_replies.get(2, back_inserter(mget_cmd_result));

    // ***** Generic Command Interface *****

    // There's no *Redis::client_getname* interface.
    // But you can use *Redis::command* to get the client name.
    val = redis.command<OptionalString>("client", "getname");
    if (val) {
        std::cout << *val << std::endl;
    }

    // Same as above.
    auto getname_cmd_str = {"client", "getname"};
    val = redis.command<OptionalString>(getname_cmd_str.begin(), getname_cmd_str.end());

    // There's no *Redis::sort* interface.
    // But you can use *Redis::command* to send sort the list.
    std::vector<std::string> sorted_list;
    redis.command("sort", "list", "ALPHA", std::back_inserter(sorted_list));

    // Another *Redis::command* to do the same work.
    auto sort_cmd_str = {"sort", "list", "ALPHA"};
    redis.command(sort_cmd_str.begin(), sort_cmd_str.end(), std::back_inserter(sorted_list));

    // ***** Redis Cluster *****

    // Create a RedisCluster object, which is movable but NOT copyable.
    auto redis_cluster = RedisCluster("tcp://127.0.0.1:7000");

    // RedisCluster has similar interfaces as Redis.
    redis_cluster.set("key", "value");
    val = redis_cluster.get("key");
    if (val) {
        std::cout << *val << std::endl;
    }   // else key doesn't exist.

    // Keys with hash-tag.
    redis_cluster.set("key{tag}1", "val1");
    redis_cluster.set("key{tag}2", "val2");
    redis_cluster.set("key{tag}3", "val3");

    std::vector<OptionalString> hash_tag_res;
    redis_cluster.mget({"key{tag}1", "key{tag}2", "key{tag}3"},
            std::back_inserter(hash_tag_res));

} catch (const Error &e) {
    // Error handling.
}

3 分布式缓存 —— redis集群

3.1 持久化

  • 单节点Redis的问题:1. 数据丢失 2. 并发能力 3. 存储能力 4. 故障恢复

3.1.1 RDB

image-20240427230804132

image-20240427233636584

3.1.2 RDB底层原理

image-20240427234336347

3.1.3 AOF持久化

image-20240427235256612

  • 默认选择appendfsync everysec

image-20240427235540933

  • 解决AOF文件过大的问题(清除无效数据) —— 执行bgrewriteaof命令

image-20240428000342657

3.1.4 AOF与RDB的对比

image-20240428200406918

3.2 Redis主从

3.2.1 搭建主从集群

(转Redis集群.md)

3.2.2 数据同步原理

  1. 全量同步
  • id不同- > 生成RDB做全量同步
  • id相同 -> 通过offset做增量同步

image-20240428202606843

image-20240428202728682

  1. 增量同步

11111

  • 如何优化主从集群同步

image-20240428203425431

3.3 Redis哨兵

image-20240428205054062

Sentinel监控原理

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令

主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。

客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

选择新的master

image-20240428205910199

如何实现故障转移

image-20240428210025947

3.3.1 搭建哨兵集群

(转Redis集群.md)

3.3.2 Redis客户端状态感知

3.4 Redis分片集群

3.4.1 搭建分片集群

(转Redis集群.md)

image-20240428223237874

3.4.2 散列插槽

image-20240428225102178

  • 如何将同一类数据固定的保存在同一个Redis实例中

image-20240428225417930

3.4.3 集群伸缩

  • 创建新Redis,加入到集群中

image-20240428225728626

  • 分配插槽
redis-cli --cluster reshard ip:port

3.4.4 故障转移

  1. 自动转移
  • 一个服务突然宕机,slave节点自动转移成master
  1. 手动转移

image-20240428231148079

4 多级缓存

image-20240428232744878

4.1 JVM进程缓存

4.2 OpenResty

image-20240429231721675

image-20240429234315794

  1. 修改nginx.conf文件

image-20240429235323238

  1. 编写item.lua文件

image-20240429235435025

  • 获取请求参数

image-20240429235839151

  • 封装http请求,由OpenResty发送给后端

image-20240430001548649

image-20240430001527599

  • 使用common.lua,通过item.lua发送请求到后端

image-20240430003124528

  • Redis预热

  • OpenResty访问Redis缓存

image-20240501150214696

  • nginx本地缓存

4.3 缓存同步

image-20240502121041244

4.3.1 Canel

image-20240502121331454

image-20240502220556739

5 Redis实践优化

5.1 key的设计

image-20240502221558171

  • 什么是Big Key

单个key的value小于10KB

对于集合类型的key,建议元素数量小于1000

  • Big Key的危害

image-20240502222457055

  • 删除Big Key

image-20240502223603980

5.2 批处理优化

  • 批处理一次性执行太多任务会阻塞网络
  1. 原生的M操作
  2. Pipeline
  • pipeline的多个命令不具有原子性

image-20240503115012875

5.2.1 集群模式下的批处理

image-20240503120412597

5.3 服务端优化

5.3.1 持久化配置

image-20240503223951603

5.3.2 慢查询

  • 该配置重启会恢复,要用就配置可以修改配置文件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 其他命令

image-20240504000236684

5.3.3 服务器安全配置

image-20240504135349697

  • 安全配置
  1. Redis一定要设置密码
  2. 禁止线上使用下面命令: keys、flushall、flushdb、config set等命令。可以利用rename-command禁用。(在redis.conf文件下设置 rename-command keys xxx123xxxdfsda
  3. bind:限制网卡,禁止外网网卡访问禁止线上使用下面命令(在redis.conf文件下设置)
  4. 开启防火墙开启防火墙
  5. 不要使用Root账户启动Redis
  6. 尽量不要使用默认端口

5.3.4 内存配置

image-20240504140451848

  • 查看内存使用情况的命令:
    • memory xxx
    • info memory

image-20240504142118346

  • 两个查看客户端链接信息的命令
    • info client
    • client list

5.3.5 集群相关问题

  • 集群的完整性问题

image-20240504143153125

  • 集群的带宽问题

image-20240504143434456

  • 集群带来的其他问题

image-20240504143734732

6 Redis底层原理

6.1 底层数据结构

6.1.1 SDS动态数组

image-20240504150555378

image-20240504150612583

6.1.2 Intset

image-20240504150909130

  • intset升级

image-20240504152243964

  • 优点
  1. Redis会确保Intset中的元素唯一、有序
  2. 具备类型升级机制,可以节省内存空间
  3. 底层采用二分查找方式来查询

6.1.3 Dict

  • Dict由三部分组成:

image-20240504153208343

image-20240504153407129

  • Dict的扩容机制

image-20240504163735702

  • 渐进式rehash

ss

6.1.4 ZipList

image-20240504165810053

image-20240504170359861

  • encoding编码(小端)

    • 字符串类型编码(00、01、10开头)

      image-20240504171221619

    • 整数类型编码

  • 连锁更新问题

image-20240504230957638

6.1.5 QuickList

  • QuickList = LinkList + ZipList

  • QuickList:限制ZipList的大小,解决内存分配的效率问题

image-20240504233808521

  • 如何限制ZipList大小

image-20240504233856667

  • QuickList节点压缩image-20240504234159575

image-20240504235503333

image-20240504235643390

6.1.5 SkipList

image-20240505000844632

  • 底层结构

image-20240505001646311

image-20240505001031349

6.1.6 RedisObject

image-20240507103139134

  • 11种编码格式

image-20240507103439069

  • 数据类型对应的编码格式

image-20240507103733752

6.2 五种数据结构

6.2.1 String

  • raw:其基本编码方式是RAW,基于简单动态字符串(SDS)实现,存储上限为512mb。
  • embstr:如果存储的SDS长度小于44字节,则会采用EMBSTR编码,此时object head与SDS是一段连续空间。申请内存时只需要调用一次内存分配函数,效率更高。
  • int:如果存储的字符串是整数值,并且大小在LONG_MAX范围内,则会采用INT编码:直接将数据保存在RedisObject的ptr指针位置(刚好8字节),不再需要SDS了。

image-20240507105438669

6.2.2 List

image-20240507110929648

6.2.3 Set

Set是Redis中的集合,不一定确保元素有序,可以满足元素唯一、查询效率要求极高。

  • Dict:为了查询效率和唯一性,set采用HT编码(Dict)。Dict中的key用来存储元素, value统一为null。

  • IIntSet:当存储的所有数据都是整数,并且元素数量不超过set-max-intset-entries时,Set会采用IntSet编码,以节省内存。

image-20240507112417630

  • 插入时类型转换

image-20240507112431813

6.2.4 ZSet

zset底层数据结构必须满足键值存储、键必须唯一、可排序这几个需求

  • SkipList:可以排序,并且可以同时存储score和ele值( member)
  • HT ( Dict):可以键值存储,并且可以根据key找value

image-20240507153935285

  • 当元素不多时,使用ZipList编码

image-20240507154502329

image-20240507154916702

6.2.5 Hash

image-20240507155424965

6.3 Redis网络模型

6.3.1 selecct

image-20240507203420468

6.3.2 poll

image-20240507203831453

6.3.3 epoll

image-20240507205127392

6.3.4 Redis网络模型

单线程?多线程?

image-20240507212223799

image-20240507222739878

6.4 Redis通信协议

image-20240510101118195

7 Redis实战

7.1 短信登录

image-20240905170425429

image-20240905170443544

7.2 商户查询缓存

tXZN6w-1725528160173)]

6.2.4 ZSet

zset底层数据结构必须满足键值存储、键必须唯一、可排序这几个需求

  • SkipList:可以排序,并且可以同时存储score和ele值( member)
  • HT ( Dict):可以键值存储,并且可以根据key找value

[外链图片转存中…(img-zQwHt0dx-1725528160173)]

  • 当元素不多时,使用ZipList编码

[外链图片转存中…(img-SCoUVdDn-1725528160173)]

[外链图片转存中…(img-KIqmlnJz-1725528160173)]

6.2.5 Hash

[外链图片转存中…(img-YExQQbXg-1725528160174)]

6.3 Redis网络模型

6.3.1 selecct

[外链图片转存中…(img-fFzuys3R-1725528160174)]

6.3.2 poll

[外链图片转存中…(img-OxEyBeGi-1725528160174)]

6.3.3 epoll

[外链图片转存中…(img-0SEZ3rgN-1725528160174)]

6.3.4 Redis网络模型

单线程?多线程?

[外链图片转存中…(img-fRIrVeDR-1725528160175)]

[外链图片转存中…(img-YhYlOECO-1725528160175)]

6.4 Redis通信协议

[外链图片转存中…(img-nUoZADFd-1725528160175)]

7 Redis实战

7.1 短信登录

[外链图片转存中…(img-auMEyc95-1725528160175)]

[外链图片转存中…(img-cedX1Yyj-1725528160176)]

7.2 商户查询缓存

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

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

相关文章

SpringBoot2:请求处理原理分析-接口参数的常用注解

1、PathVariable 作用说明&#xff1a;获取路径参数 案例&#xff1a; 接口收参形式&#xff1a; GetMapping("/car/{id}/owner/{username}")public Map<String,Object> getCar(PathVariable("id") Integer id,PathVariable("username")…

echarts圆饼图定时器动画

(function () {const WdxjEcharts echarts.init(document.getElementById(wdxjEchart))let num 0;var imgURL "../imagesNew/wd-center.png";var trafficWay [{name: 火车,value: 20}, {name: 飞机,value: 10}, {name: 客车,value: 30}, {name: 轮渡,value: 40}]…

深入解读Docker核心网络管理:架构、模式与通信机制

在容器化技术中&#xff0c;网络管理是影响容器通信和应用部署的重要组成部分。Docker不仅简化了应用的部署过程&#xff0c;还提供了强大的网络管理功能&#xff0c;确保容器之间以及容器与外部系统的网络通信能够高效、稳定地进行。 本文将深入解读Docker的核心网络管理原理…

查看hprof文件

hprof可以用来分析某个进程的内存情况&#xff0c;对我们分析内存泄漏问题有很大帮助&#xff0c;本文主要记录如何生成及查看hprof文件。 1生成.hprof文件 可以使用adb命令生成 .hprof文件&#xff0c;生成的是在执行命令的那一刻&#xff0c;该进程的内存情况&#xff1a; …

后端Web之SpringBoot原理

目录 1.配置优先级 2.Bean 3.SpringBoot原理 1.配置优先级 SpringBoot中支持三种格式的配置文件: .application.properties、application.yml和application. yaml。它们的配置优先级分别降低。虽然springboot支持多种格式配置文件&#xff0c;但是在项目开发时,推荐统一使用…

视频智能分析平台LntonAIServer安防监控平台花屏检测、马赛克检测功能介绍

视频监控系统在现代社会中扮演着至关重要的角色&#xff0c;无论是用于安全监控、交通管理还是其他用途&#xff0c;视频的质量直接关系到系统的可靠性和有效性。LntonAIServer通过新增的视频质量诊断功能&#xff0c;包括花屏检测和马赛克检测&#xff0c;进一步增强了视频监控…

读书学习进阶笔记 # Datawhale X 李宏毅苹果书 AI夏令营

文章目录 &#x1f6a9;学习目标&#x1f6a9;学习内容&#x1f6a9; Task1.1&#x1f3af;为什么优化会失败&#x1f4cc;因非信息梯度导致的失败 &#x1f3af;局部极小值与鞍点&#x1f3af;临界点及其种类&#x1f3af;如何判断临界值种类&#x1f4cc;更简便的方法来判断 …

Unity教程(十四)敌人空闲和移动的实现

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

MT6895(天玑8100)处理器规格参数_MTK联发科平台方案

MT6895平台 采用台积电5nm工艺&#xff0c;与天玑 8000 相比性能提升 20% &#xff0c;搭载4 个 2.85GHz A78 核心 4 个 2.0GHz A55 核心&#xff0c;CPU能效比上一代提高 25% 。GPU 采用了第三代的Valhall Arm Mali-G610 MC6架构&#xff0c;拥有6核心&#xff0c;搭配天玑81…

ubuntu22.04 qemu 安装windows on arm虚拟机

ubuntu22.04 qemu 安装windows on arm虚拟机 iso: https://uupdump.net/ https://massgrave.dev/windows_arm_links vivo driver: https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.262-2/ qemu sudo apt update sudo a…

Java笔试面试题AI答之JDBC(1)

文章目录 1. 什么是JDBC&#xff1f;2. 驱动(Driver)在JDBC中的角色&#xff1f;3. JDBC PreparedStatement比Statement有什么优势&#xff1f;1. 预编译和性能提升2. 参数化查询和安全性3. 更好的可读性和可维护性4. 支持批量操作5. 缓存机制&#xff08;特定数据库环境&#…

【自考zt】【数据结构】【21.10】

【关键字】 数据元素基本单位、抽象数据类型、上三角压缩对称矩阵、排序O&#xff08;n2&#xff09;、不宜链表快排 循环队列入队下标、二叉链表空指针、无相连通图边数差、B树非根结点关键字 链栈无头结点 单链表前二节点和、邻接矩阵度、二叉排序树 一、单选 二、填…

WGCLOUD可以监测交换机的哪些指标数据

WGCLOUD有个模块SNMP监测&#xff0c;可以用于监测交换机、防火墙等设备 监测的指标包括&#xff1a;上行流量&#xff0c;下行流量&#xff0c;每个接口的传输速率&#xff08;包括上行和下行&#xff09;&#xff0c;每个接口的状态&#xff0c;基本信息&#xff0c;温度&am…

Kafka【十一】数据一致性与高水位(HW :High Watermark)机制

【1】数据一致性 Kafka的设计目标是&#xff1a;高吞吐、高并发、高性能。为了做到以上三点&#xff0c;它必须设计成分布式的&#xff0c;多台机器可以同时提供读写&#xff0c;并且需要为数据的存储做冗余备份。 图中的主题有3个分区&#xff0c;每个分区有3个副本&#xf…

解决商店汽水兑换问题——利用贪心算法与循环结构

解决商店汽水兑换问题——利用贪心算法与循环结构 在某商店中,有一种特别的促销活动:三个空汽水瓶可以换一瓶汽水。而且,如果空瓶数量不足,还可以向老板借空瓶(但必须要归还)。给定初始的空瓶数量,如何计算最多可以喝到多少瓶汽水?这个问题可以通过贪心算法来高效解决…

windows手工杀毒-寻找可疑进程之线程

上篇回顾&#xff1a;windows手工杀毒-寻找可疑进程之进程模块-CSDN博客 上篇我们介绍了如何通过进程模块寻找可疑进程&#xff0c;进程模块文件按照PE格式存储&#xff0c;我们可以使用IDA等静态分析&#xff08;不需要运行文件&#xff0c;只看文件内容&#xff09;工…

仕考网:军队文职人员公开招考笔试考试大纲

考试方式和时限 考试方式为闭卷笔试&#xff0c;考试时限为120分钟。 试卷分值和试题类型 试卷满分为100分&#xff0c;试题类型为客观性试题。 测查内容 测查内容主要包括基本知识和岗位能力&#xff0c;具体内容如下。 1.基本知识 2.岗位能力 ①言语理解与表达 ②数…

redis主从+高可用切换+负载均衡

1. redis主从配置 # 在master中 cp sentinel.conf /etc/redis/ vim /etc/redis/sentinel.conf scp /etc/redis/sentinel.conf server2:/etc/redis/ scp /etc/redis/sentinel.conf server3:/etc/redis/ redis-sentinel /etc/redis/sentinel.conf # 启动监控# 在slave中 redis-s…

Java SpringBoot集成Vue.js,构建茶园茶农文化交流平台,四步实现高效互动,MySQL存储数据更稳定

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

LevelDB RockesDB LSM

LevelDB levelDB是同样也是一个Key-value数据库&#xff0c;但是相对于Redis、memcache来说&#xff0c;levelDB是基于内存-磁盘来实现的&#xff0c;但在大部分场景下也表现出了不逊色于Redis、Memcache的性能。levelDB由google实现并开源&#xff0c;轻松支持billion量级的数…