flea-cache使用之Redis哨兵模式接入
Redis哨兵模式接入
- 1. 参考
- 2. 依赖
- 3. 基础接入
- 3.1 定义Flea缓存接口
- 3.2 定义抽象Flea缓存类
- 3.3 定义Redis客户端接口类
- 3.4 定义Redis客户端命令行
- 3.5 定义哨兵模式Redis客户端实现类
- 3.6 定义Redis哨兵连接池
- 3.7 定义Redis哨兵配置文件
- 3.8 定义Redis Flea缓存类
- 3.9 定义抽象Flea缓存管理类
- 3.10 定义Redis哨兵模式Flea缓存管理类
- 3.11 定义Redis客户端工厂类
- 3.12 定义Redis客户端策略上下文
- 3.13 定义哨兵模式Redis客户端策略
- 3.14 Redis集群模式接入自测
- 4. 进阶接入
- 4.1 定义抽象Spring缓存
- 4.2 定义Redis Spring缓存类
- 4.3 定义抽象Spring缓存管理类
- 4.4 定义Redis哨兵模式Spring缓存管理类
- 4.5 spring 配置
- 4.6 缓存自测
- 结语
1. 参考
flea-cache使用之Redis哨兵模式接入 源代码
2. 依赖
jedis-3.0.1.jar
<!-- Java redis -->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.0.1</version>
</dependency>
spring-context-4.3.18.RELEASE.jar
<!-- Spring相关 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.18.RELEASE</version>
</dependency>
spring-context-support-4.3.18.RELEASE.jar
<dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>4.3.18.RELEASE</version>
</dependency>
3. 基础接入
3.1 定义Flea缓存接口
IFleaCache 可参考笔者的这篇博文 Memcached接入,不再赘述。
3.2 定义抽象Flea缓存类
AbstractFleaCache 可参考笔者的这篇博文 Memcached接入,不再赘述。
3.3 定义Redis客户端接口类
RedisClient 可参考笔者的这篇博文 Redis集群模式接入,不再赘述。
3.4 定义Redis客户端命令行
RedisClientCommand 可参考笔者的这篇博文 Redis分片模式接入,不再赘述。
3.5 定义哨兵模式Redis客户端实现类
FleaRedisSentinelClient 即Flea哨兵模式Redis客户端实现,封装了Flea框架操作Redis缓存的基本操作。它内部具体操作Redis缓存的功能,由Jedis哨兵连接池获取Jedis实例对象完成,包含读、写、删除Redis缓存的基本操作方法。
哨兵模式下,单个缓存接入场景,可通过如下方式使用:
RedisClient redisClient = new FleaRedisSentinelClient.Builder().build();// 执行读,写,删除等基本操作redisClient.set("key", "value");
哨兵模式下,整合缓存接入场景,可通过如下方式使用:
RedisClient redisClient = new FleaRedisSentinelClient.Builder(poolName).build();// 执行读,写,删除等基本操作redisClient.set("key", "value");
当然每次都新建Redis客户端显然不可取,我们可通过Redis客户端工厂获取Redis客户端。
哨兵模式下,单个缓存接入场景,可通过如下方式使用:
RedisClient redisClient = RedisClientFactory.getInstance(CacheModeEnum.SENTINEL);
哨兵模式下,整合缓存接入场景,可通过如下方式使用:
RedisClient redisClient = RedisClientFactory.getInstance(poolName, CacheModeEnum.SENTINEL);
public class FleaRedisSentinelClient extends FleaRedisClient {private JedisSentinelPool jedisSentinelPool;private int maxAttempts;/*** Redis哨兵客户端构造方法 (默认)** @since 2.0.0*/private FleaRedisSentinelClient() {this(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME);}/*** Redis哨兵客户端构造方法(指定连接池名)** @param poolName 连接池名* @since 2.0.0*/private FleaRedisSentinelClient(String poolName) {super(poolName);init();}/*** 初始化Jedis哨兵实例** @since 2.0.0*/private void init() {if (CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME.equals(getPoolName())) {jedisSentinelPool = RedisSentinelPool.getInstance().getJedisSentinelPool();maxAttempts = RedisSentinelConfig.getConfig().getMaxAttempts();} else {jedisSentinelPool = RedisSentinelPool.getInstance(getPoolName()).getJedisSentinelPool();maxAttempts = CacheConfigUtils.getMaxAttempts();}}@Overridepublic String set(final String key, final Object value) {return new RedisClientCommand<String, JedisSentinelPool, Jedis>(this.jedisSentinelPool, this.maxAttempts) {@Overridepublic String execute(Jedis connection) {if (value instanceof String)return connection.set(key, (String) value);elsereturn connection.set(SafeEncoder.encode(key), ObjectUtils.serialize(value));}}.run();}// 省略。。。。。。/*** 内部建造者类** @author huazie* @version 2.0.0* @since 2.0.0*/public static class Builder {private String poolName; // 连接池名/*** 默认构造器** @since 2.0.0*/public Builder() {}/*** 指定连接池的构造器** @param poolName 连接池名* @since 2.0.0*/public Builder(String poolName) {this.poolName = poolName;}/*** 构建Redis哨兵客户端对象** @return Redis哨兵客户端* @since 2.0.0*/public RedisClient build() {if (StringUtils.isBlank(poolName)) {return new FleaRedisSentinelClient();} else {return new FleaRedisSentinelClient(poolName);}}}
}
该类的构造函数初始化逻辑,可以看出我们使用了 RedisSentinelPool
, 下面来介绍一下。
3.6 定义Redis哨兵连接池
我们使用 RedisSentinelPool 来初始化Jedis哨兵连接池实例,其中重点是获取分布式Jedis连接池 ShardedJedisPool
,该类其中一个构造方法如下:
public JedisSentinelPool(String masterName, Set<String> sentinels, final GenericObjectPoolConfig poolConfig, final int connectionTimeout, final int soTimeout, final String password, final int database, final String clientName) {}
Redis哨兵连接池,用于初始化Jedis哨兵连接池实例。
针对单独缓存接入场景,采用默认连接池初始化的方式; 可参考如下:
// 初始化默认连接池RedisSentinelPool.getInstance().initialize();
针对整合缓存接入场景,采用指定连接池初始化的方式; 可参考如下:
// 初始化指定连接池RedisSentinelPool.getInstance(group).initialize(cacheServerList);
public class RedisSentinelPool {private static final ConcurrentMap<String, RedisSentinelPool> redisPools = new ConcurrentHashMap<>();private static final Object redisSentinelPoolLock = new Object();private String poolName; // 连接池名private JedisSentinelPool jedisSentinelPool; // Jedis哨兵连接池private RedisSentinelPool(String poolName) {this.poolName = poolName;}/*** 获取Redis哨兵连接池实例 (默认连接池)** @return Redis哨兵连接池实例对象* @since 2.0.0*/public static RedisSentinelPool getInstance() {return getInstance(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME);}/*** 获取Redis哨兵连接池实例 (指定连接池名)** @param poolName 连接池名* @return Redis哨兵连接池实例对象* @since 2.0.0*/public static RedisSentinelPool getInstance(String poolName) {if (!redisPools.containsKey(poolName)) {synchronized (redisSentinelPoolLock) {if (!redisPools.containsKey(poolName)) {RedisSentinelPool redisSentinelPool = new RedisSentinelPool(poolName);redisPools.put(poolName, redisSentinelPool);}}}return redisPools.get(poolName);}/*** 默认初始化** @since 2.0.0*/public void initialize(int database) {// 省略。。。。。。}/*** 初始化 (非默认连接池)** @param cacheServerList 缓存服务器集* @since 2.0.0*/public void initialize(List<CacheServer> cacheServerList) {// 省略。。。。。。}/*** Jedis哨兵连接池** @return Jedis哨兵连接池* @since 2.0.0*/public JedisSentinelPool getJedisSentinelPool() {if (ObjectUtils.isEmpty(jedisSentinelPool)) {ExceptionUtils.throwFleaException(FleaCacheConfigException.class, "获取Jedis哨兵连接池失败:请先调用initialize初始化");}return jedisSentinelPool;}
}
3.7 定义Redis哨兵配置文件
flea-cache 读取 redis.sentinel.properties(Redis哨兵配置文件),用作初始化 RedisSentinelPool
# Redis哨兵配置
redis.sentinel.switch=1redis.systemName=FleaFrameredis.sentinel.masterName=mymasterredis.sentinel.server=127.0.0.1:36379,127.0.0.1:36380,127.0.0.1:36381#redis.sentinel.password=huazie123redis.sentinel.connectionTimeout=2000redis.sentinel.soTimeout=2000# Redis哨兵客户端连接池配置
redis.pool.maxTotal=100redis.pool.maxIdle=10redis.pool.minIdle=0redis.pool.maxWaitMillis=2000redis.maxAttempts=5redis.nullCacheExpiry=10
redis.sentinel.switch
: Redis哨兵配置开关(1:开启 0:关闭),如果不配置也默认开启redis.systemName
: Redis缓存所属系统名redis.sentinel.masterName
: Redis主服务器节点名称redis.sentinel.server
: Redis哨兵节点的地址集合redis.sentinel.password
: Redis主从服务器节点登录密码(各节点配置同一个)redis.sentinel.connectionTimeout
: Redis哨兵客户端socket连接超时时间(单位:ms)redis.sentinel.soTimeout
: Redis哨兵客户端socket读写超时时间(单位:ms)redis.pool.maxTotal
: Jedis连接池最大连接数redis.pool.maxIdle
: Jedis连接池最大空闲连接数redis.pool.minIdle
: Jedis连接池最小空闲连接数redis.pool.maxWaitMillis
: Jedis连接池获取连接时的最大等待时间(单位:ms)redis.maxAttempts
: Redis客户端操作最大尝试次数【包含第一次操作】redis.nullCacheExpiry
: 空缓存数据有效期(单位:s)
3.8 定义Redis Flea缓存类
RedisFleaCache 可参考笔者的这篇博文 Redis分片模式接入,不再赘述。
3.9 定义抽象Flea缓存管理类
AbstractFleaCacheManager 可参考笔者的这篇博文 Memcached接入,不再赘述。
3.10 定义Redis哨兵模式Flea缓存管理类
RedisSentinelFleaCacheManager 继承抽象Flea缓存管理类 AbstractFleaCacheManager
,用于接入Flea框架管理Redis缓存。
它的默认构造方法,用于初始化哨兵模式下默认连接池的Redis客户端【默认Redis数据库索引为0】, 这里需要先初始化Redis哨兵连接池,默认连接池名为【default
】; 然后通过 RedisClientFactory
获取哨兵模式下默认连接池的Redis客户端 RedisClient
,可在 3.11 查看。
它的带参数的构造方法,用于初始化哨兵模式下默认连接池的Redis客户端【指定Redis数据库索引】。
方法 newCache
用于创建一个 RedisFleaCache
的实例对象,它里面包含了 读、写、删除 和 清空 缓存的基本操作,每一类 Redis 缓存数据都对应了一个 RedisFleaCache
的实例对象。
public class RedisSentinelFleaCacheManager extends AbstractFleaCacheManager {private RedisClient redisClient; // Redis客户端/*** 默认构造方法,初始化哨兵模式下默认连接池的Redis客户端** @since 2.0.0*/public RedisSentinelFleaCacheManager() {this(0);}/*** 初始化哨兵模式下默认连接池的Redis客户端,指定Redis数据库索引** @since 2.0.0*/public RedisSentinelFleaCacheManager(int database) {if (!RedisSentinelConfig.getConfig().isSwitchOpen()) return;// 初始化默认连接池RedisSentinelPool.getInstance().initialize(database);// 获取哨兵模式下默认连接池的Redis客户端redisClient = RedisClientFactory.getInstance(CacheModeEnum.SENTINEL);}@Overrideprotected AbstractFleaCache newCache(String name, int expiry) {int nullCacheExpiry = RedisSentinelConfig.getConfig().getNullCacheExpiry();if (RedisSentinelConfig.getConfig().isSwitchOpen())return new RedisFleaCache(name, expiry, nullCacheExpiry, CacheModeEnum.SENTINEL, redisClient);elsereturn new EmptyFleaCache(name, expiry, nullCacheExpiry);}
}
3.11 定义Redis客户端工厂类
RedisClientFactory ,有四种方式获取 Redis 客户端:
- 一是获取分片模式下默认连接池的 Redis 客户端,应用在单个缓存接入场景;
- 二是获取指定模式下默认连接池的 Redis 客户端,应用在单个缓存接入场景【3.10 采用】;
- 三是获取分片模式下指定连接池的 Redis 客户端,应用在整合缓存接入场景;
- 四是获取指定模式下指定连接池的 Redis 客户端,应用在整合缓存接入场景。
/*** Redis客户端工厂,用于获取Redis客户端。** @author huazie* @version 1.1.0* @since 1.0.0*/
public class RedisClientFactory {private static final ConcurrentMap<String, RedisClient> redisClients = new ConcurrentHashMap<>();private static final Object redisClientLock = new Object();private RedisClientFactory() {}/*** 获取分片模式下默认连接池的Redis客户端** @return 分片模式的Redis客户端* @since 1.0.0*/public static RedisClient getInstance() {return getInstance(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME);}/*** 获取指定模式下默认连接池的Redis客户端** @param mode 缓存模式* @return 指定模式的Redis客户端* @since 1.1.0*/public static RedisClient getInstance(CacheModeEnum mode) {return getInstance(CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME, mode);}/*** 获取分片模式下指定连接池的Redis客户端** @param poolName 连接池名* @return 分片模式的Redis客户端* @since 1.0.0*/public static RedisClient getInstance(String poolName) {return getInstance(poolName, CacheModeEnum.SHARDED);}/*** 获取指定模式下指定连接池的Redis客户端** @param poolName 连接池名* @param mode 缓存模式* @return 指定模式的Redis客户端* @since 1.1.0*/public static RedisClient getInstance(String poolName, CacheModeEnum mode) {String key = StringUtils.strCat(poolName, CommonConstants.SymbolConstants.UNDERLINE, StringUtils.valueOf(mode.getMode()));if (!redisClients.containsKey(key)) {synchronized (redisClientLock) {if (!redisClients.containsKey(key)) {RedisClientStrategyContext context = new RedisClientStrategyContext(poolName);redisClients.putIfAbsent(key, FleaStrategyFacade.invoke(mode.name(), context));}}}return redisClients.get(key);}
}
在上面 的 getInstance(String poolName, CacheModeEnum mode)
方法中,使用了 RedisClientStrategyContext ,用于定义 Redis 客户端策略上下文。根据不同的缓存模式,就可以找到对应的 Redis 客户端策略。
3.12 定义Redis客户端策略上下文
RedisClientStrategyContext 可参考笔者的这篇博文 Redis分片模式接入,不再赘述。
3.13 定义哨兵模式Redis客户端策略
RedisSentinelClientStrategy 用于新建一个 Flea Redis
哨兵客户端。
/*** 哨兵模式Redis客户端 策略** @author huazie* @version 2.0.0* @since 2.0.0*/
public class RedisSentinelClientStrategy implements IFleaStrategy<RedisClient, String> {@Overridepublic RedisClient execute(String poolName) throws FleaStrategyException {RedisClient originRedisClient;// 新建一个Flea Redis哨兵客户端类实例if (CommonConstants.FleaPoolConstants.DEFAULT_POOL_NAME.equals(poolName)) {originRedisClient = new FleaRedisSentinelClient.Builder().build();} else {originRedisClient = new FleaRedisSentinelClient.Builder(poolName).build();}return originRedisClient;}
}
好了,到这里我们可以来测试 Redis 哨兵模式。
3.14 Redis集群模式接入自测
单元测试类 FleaCacheTest
首先,这里需要按照 Redis哨兵配置文件 中的地址部署相应的 Redis哨兵服务 和 Redis主从服务,后续有机会我再出一篇简单的Redis主从 + 哨兵的搭建博文。
@Testpublic void testRedisSentinelFleaCache() {try {// 哨兵模式下Flea缓存管理类,复用原有获取方式
// AbstractFleaCacheManager manager = FleaCacheManagerFactory.getFleaCacheManager(CacheEnum.RedisSentinel.getName());// 哨兵模式下Flea缓存管理类,指定数据库索引AbstractFleaCacheManager manager = FleaCacheManagerFactory.getFleaCacheManager(0);AbstractFleaCache cache = manager.getCache("fleajerseyresource");LOGGER.debug("Cache={}", cache);//#### 1. 简单字符串cache.put("author", "huazie");cache.put("other", null);
// cache.get("author");
// cache.get("other");
// cache.delete("author");
// cache.delete("other");
// cache.clear();cache.getCacheKey();LOGGER.debug(cache.getCacheName() + ">>>" + cache.getCacheDesc());} catch (Exception e) {LOGGER.error("Exception:", e);}}
4. 进阶接入
4.1 定义抽象Spring缓存
AbstractSpringCache 可参考笔者的这篇博文 Memcached接入,不再赘述。
4.2 定义Redis Spring缓存类
RedisSpringCache 可参考笔者的这篇博文 Redis分片模式接入,不再赘述。
4.3 定义抽象Spring缓存管理类
AbstractSpringCacheManager 可参考笔者的这篇博文 Memcached接入,不再赘述。
4.4 定义Redis哨兵模式Spring缓存管理类
RedisSentinelSpringCacheManager 继承抽象 Spring 缓存管理类 AbstractSpringCacheManager
,用于接入Spring框架管理Redis缓存; 基本实现同 RedisSentinelFleaCacheManager,唯一不同在于 newCache 的实现。
它的默认构造方法,用于初始化哨兵模式下默认连接池的Redis客户端【默认Redis数据库索引为0】, 这里需要先初始化Redis哨兵连接池,默认连接池名为【default
】; 然后通过 RedisClientFactory
获取哨兵模式下默认连接池的Redis客户端 RedisClient
,可在 3.11 查看。
它的带参数的构造方法,用于初始化哨兵模式下默认连接池的Redis客户端【指定Redis数据库索引】。
方法【newCache
】用于创建一个Redis Spring缓存, 而它内部是由Redis Flea缓存实现具体的 读、写、删除 和 清空 缓存的基本操作。
public class RedisSentinelSpringCacheManager extends AbstractSpringCacheManager {private RedisClient redisClient; // Redis客户端/*** 默认构造方法,初始化哨兵模式下默认连接池的Redis客户端** @since 2.0.0*/public RedisSentinelSpringCacheManager() {this(0);}/*** 初始化哨兵模式下默认连接池的Redis客户端,指定Redis数据库索引** @since 2.0.0*/public RedisSentinelSpringCacheManager(int database) {if (!RedisSentinelConfig.getConfig().isSwitchOpen()) return;// 初始化默认连接池RedisSentinelPool.getInstance().initialize(database);// 获取哨兵模式下默认连接池的Redis客户端redisClient = RedisClientFactory.getInstance(CacheModeEnum.SENTINEL);}@Overrideprotected AbstractSpringCache newCache(String name, int expiry) {int nullCacheExpiry = RedisSentinelConfig.getConfig().getNullCacheExpiry();if (RedisSentinelConfig.getConfig().isSwitchOpen())return new RedisSpringCache(name, expiry, nullCacheExpiry, CacheModeEnum.SENTINEL, redisClient);elsereturn new RedisSpringCache(name, new EmptyFleaCache(name, expiry, nullCacheExpiry));}}
4.5 spring 配置
如下用于配置缓存管理 redisSentinelSpringCacheManager
,其中 configMap
为缓存时间(key
缓存对象名称 value
缓存过期时间)
<bean id="redisSentinelSpringCacheManager" class="com.huazie.fleaframework.cache.redis.manager.RedisSentinelSpringCacheManager"><!-- 使用带参数的构造函数实例化,指定Redis数据库索引 --><!--<constructor-arg index="0" value="0"/>--><property name="configMap"><map><entry key="fleajerseyi18nerrormapping" value="86400"/><entry key="fleajerseyresservice" value="86400"/><entry key="fleajerseyresclient" value="86400"/><entry key="fleajerseyresource" value="86400"/></map></property></bean><!-- 开启缓存 --><cache:annotation-driven cache-manager="redisSentinelSpringCacheManager" proxy-target-class="true"/>
4.6 缓存自测
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringCacheTest {private static final FleaLogger LOGGER = FleaLoggerProxy.getProxyInstance(SpringCacheTest.class);@Autowired@Qualifier("redisSentinelSpringCacheManager")private AbstractSpringCacheManager redisSentinelSpringCacheManager;@Testpublic void testRedisSentinelSpringCache() {try {// 哨兵模式下Spring缓存管理类AbstractSpringCache cache = redisSentinelSpringCacheManager.getCache("fleajerseyresource");LOGGER.debug("Cache = {}", cache);//#### 1. 简单字符串cache.put("menu1", "huazie");cache.put("menu2", null);
// cache.get("menu1");
// cache.get("menu2");
// cache.getCacheKey();
// cache.delete("menu1");
// cache.delete("menu2");
// cache.clear();cache.getCacheKey();AbstractFleaCache fleaCache = (AbstractFleaCache) cache.getNativeCache();LOGGER.debug(fleaCache.getCacheName() + ">>>" + fleaCache.getCacheDesc());} catch (Exception e) {LOGGER.error("Exception:", e);}}
}
结语
到这一步,Redis 哨兵模式单独接入的内容终于搞定了,有关整合接入Redis哨兵模式的,请查看笔者的《整合Memcached和Redis接入》。
相关文章:
flea-cache使用之Redis哨兵模式接入
Redis哨兵模式接入 1. 参考2. 依赖3. 基础接入3.1 定义Flea缓存接口3.2 定义抽象Flea缓存类3.3 定义Redis客户端接口类3.4 定义Redis客户端命令行3.5 定义哨兵模式Redis客户端实现类3.6 定义Redis哨兵连接池3.7 定义Redis哨兵配置文件3.8 定义Redis Flea缓存类3.9 定义抽象Flea…...
【Docker】Docker环境下快速部署Ollama与Open-WebUI:详细指南
Docker环境下快速部署Ollama与Open-WebUI:详细指南 在本篇文章中,我们将深入探讨如何在Docker中高效部署 Ollama 和 Open-WebUI,并解决在实际使用中常见的问题,确保你的模型服务稳定高效地运行。 一、Ollama 和 Open-WebUI 快速部…...
FFmpeg在Android开发中的核心价值是什么?
FFmpeg 在 Android 开发中的核心价值主要体现在其强大的多媒体处理能力和灵活性上,尤其在音视频编解码、流媒体处理及跨平台兼容性方面具有不可替代的作用。以下是具体分析: --- 1. 强大的音视频编解码能力 - 支持广泛格式:FFmpeg 支持几乎所…...
Java的进制转换
进制知识 Java 中使用不同的前缀表示数据,常见的进制数据有二进制(0b)、八进制(0)、十进制(无)、十六进制(0x)。 public class Demo1 {public static void main(String…...
SpringBoot中的拦截器
SpringBoot中的拦截器 Filter 典型场景 全局鉴权/接口耗时统计 WebFilter("/*") public class CostFilter implements Filter {Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {long start System.currentTimeMill…...
使用聊天模型和提示模板构建一个简单的 LLM 应用程序
官方教程 官方案例 在上面的链接注册后,请确保设置您的环境变量以开始记录追踪 export LANGSMITH_TRACING"true" export LANGSMITH_API_KEY"..."或者,如果在笔记本中,您可以使用以下命令设置它们 import getpass imp…...
paimon中批和流查看过去的快照的数据及变动的数据
1、批处理 创建表并插入三条数据 CREATE TABLE ws_t (id INT,ts BIGINT,vc INT,PRIMARY KEY (id) NOT ENFORCED ); INSERT INTO ws_t VALUES(2,2,2),(3,3,3),(4,4,4),(5,5,5); --设置执行模式为批处理 RESET execution.checkpointing.interval; SET execution.runtime-mode …...
Linux513 rsync本地传输 跨设备传输 一
ping节点bPing通 仅主机模式不需要设置网关节点a也可以Ping通节点b 同步成功 下载文件夹成功 今日源码 节点a 节点b...
c语言第一个小游戏:贪吃蛇小游戏08(贪吃蛇完结)
贪吃蛇撞墙和想不开咬死自己 #include <curses.h> #include <stdlib.h> struct snake{ int hang; int lie; struct snake *next; }; struct snake food; struct snake *head; struct snake *tail; int key; int dir; #define UP 1 #define DOWN -1 …...
Android Native 之 自定义进程
在Android五层架构中,native层基本上全是c的世界,这些c进程基本上靠android世界的第一个进程init进程创建,init通过rc配置文件,创建了众多的c子进程,也是这众多的c进程,构建了整个android世界的native层。 …...
深度学习 自然语言处理(RNN) day_02
1. 感知机与神经网络 1.1 感知机 生物神经元: 1.1.1 感知机的概念 感知机(Perceptron),又称神经元(Neuron,对生物神经元进行了模仿)是神 经网络(深度学习)的起源算法&am…...
Kotlin 中的作用域函数
在 Kotlin 中,作用域函数是一组用于在对象上下文中执行代码块的函数。 它们通过简洁的语法实现对对象的操作和逻辑封装。 作用域函数的对比: 1 let 特点: 通过 it 访问对象,需显式使用;返回值是代码块的最后一行结果…...
Linux的SLES系统和其他几大系统之间的区别
✅ SLES 和其他主流 Linux 发行版对比表 特性/发行版SLES (SUSE Linux Enterprise Server)RHEL (Red Hat Enterprise Linux)CentOS / AlmaLinux / RockyUbuntu ServerDebian定位企业级,注重稳定性和支持企业级,行业标准,广泛应用社区版 RHEL…...
上位机学习攻略、步骤和实战路径
目录 🎯 一、什么是上位机? 🧭 二、学习步骤和路径 第一步:了解基础概念 第二步:掌握通信协议 1. 常见协议: 2. 学习目标: 第三步:熟悉主流上位机软件 可选工具及语言&#…...
【爬虫】DrissionPage-1
官网地址:DrissionPage官网 小需求采集,我喜欢,我要学。 1 介绍 这是用python编写的爬虫自动化工具,将Selenium 和 Requests 的功能巧妙地整合在一起,提供了统一又简单的操作接口。开发者可以在浏览器模式࿰…...
API安全
目录 API安全:从威胁到防护的全面解析 引言 一、API安全的定义与重要性 1.1 API安全的核心目标 1.2 API安全的挑战 二、API的常见安全威胁 2.1 身份验证攻击 2.2 中间人攻击(MITM) 2.3 注入攻击 2.4 安全配置错误 2.5 拒绝服务&…...
UDP和TCP协议
目录 1. UDP协议 1.1. UDP的特性 1.2. UDP的包头 1.3. UDP的三大使用场景和实际例子 1.4. TCP和UDP的区别 2. TCP协议 2.1. TCP包头格式 2.2. TCP包头和UDP包头对比 2.3. TCP协议的特点 2.4. TCP的三次握手(连接维护问题) 2.5. TCP的四次挥手…...
关于Go语言的开发环境的搭建
1.Go开发环境的搭建 其实对于GO语言的这个开发环境的搭建的过程,类似于java的开发环境搭建,我们都是需要去安装这个开发工具包的,也就是俗称的这个SDK,他是对于我们的程序进行编译的,不然我们写的这个代码也是跑不起来…...
【Bootstrap V4系列】学习入门教程之 组件-导航(Navs)
【Bootstrap V4系列】学习入门教程之 组件-导航(Navs) 导航(Navs)一、Base nav二、Available styles 可用样式2.1 Horizontal alignment 水平对齐2.2 Vertical 垂直的2.3 Tabs 表格样式2.4 Pills 胶囊样式2.5 Fill and justify 填…...
基于单片机的视力保护仪设计与实现
标题:基于单片机的视力保护仪设计与实现 内容:1.摘要 随着电子设备的普及,人们的视力健康面临着严峻挑战。为了有效预防近视等视力问题,本文旨在设计并实现一款基于单片机的视力保护仪。通过采用红外传感器、光敏传感器等元件,实时监测使用者…...
如何避免和恢复因终端关闭导致的 LoRA 微调中断
环境: Ubuntu20.04 Llama factory Qwen2.5-7B-Instruct llama.cpp H20 95G 问题描述: 使用命令 CUDA_VISIBLE_DEVICES1 FORCE_TORCHRUN1 llamafactory-cli train examples/train_lora/qwen2_5-7b_lora_sft.yaml 进行 LoRA 微调时,如果…...
RT-linux 系统详解
RT-Linux(Real-Time Linux)是一种基于Linux内核的实时操作系统(RTOS),旨在为Linux添加硬实时(Hard Real-Time)能力,使其适用于对时间确定性要求极高的嵌入式系统和工业控制场景。以下…...
开源网络地图可视化第六章学习指南
源代码地址:开源网络地图可视化-配套代码.zip - 蓝奏云 配套书籍:开源网络地图可视化——基于Leaflet的在线地图开发 (杨乃) (Z-Library)(1).pdf - 蓝奏云 3 第六章Leaflet地图动画 3.1 图标动画 3.1.1 沿线运动 沿线运动的动画使用了Leaflet.Geode…...
网页常见水印实现方式
文章目录 1 明水印技术实现1.1 DOM覆盖方案1.2 Canvas动态渲染1.3 CSS伪元素方案2 暗水印技术解析2.1 空域LSB算法2.2 频域傅里叶变换3 防篡改机制设计3.1 MutationObserver防护3.2 Canvas指纹追踪4 前后端实现对比5 攻防博弈深度分析5.1 常见破解手段5.2 进阶防御策略6 选型近…...
# 08_Elastic Stack 从入门到实践(八)---1
08_Elastic Stack 从入门到实践(八)—1 一、Logstash入门之简介以及部署安装 1、Elastic Stack 技术栈示意图 2、Logstash 简介 Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的“存储库”中。(存储库当然是Ela…...
携程酒店 phantom-token token1004 分析
声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 部分python代码 搞APP搞的心态有点崩…...
物理:从人体组成角度能否说明基本粒子的差异性以及组织结构的可预设性?
人类的个体差异源于粒子组合的复杂性、环境与随机性的相互作用,而非基本粒子本身的差异性。以下分层次解析: 一、基本粒子的同质性与组合多样性 1. 基本粒子的同一性 标准模型确认:同种类基本粒子(如电子、上夸克)具有完全相同的质量、电荷等属性,不存在个体差异。泡利不…...
前端面试每日三题 - Day 33
这是我为准备前端/全栈开发工程师面试整理的第33天每日三题练习: ✅ 题目1:Deno核心特性深度解析 革命性特性详解 // 安全权限控制(运行时显式授权) deno run --allow-netapi.example.com server.ts // 内置TypeScript支持 …...
JavaScript编译原理
在编程语言的世界中,编译器(如 GCC、TypeScript)和转译器(如 Babel)扮演着至关重要的角色,它们负责将人类可读的代码转换为机器或其他语言可执行的指令。这一过程通常分为四个关键阶段: 1. 词法…...
Nature图形复现—两种快速绘制热图的方法
相信大家在科研过程中,会遇到热图,有时候会觉得热图理解起来比较困难,或者觉得绘制热图也比较困难。本期教程我们来深入了解热图、绘制热图。 热图是一种通过颜色深浅或色阶变化来直观展示数据分布、密度或数值大小的可视化工具。它在多个领域…...
MySQL数据库——视图
目录 一、视图是什么? 二、特点 三、创建视图 四.查询视图 五.更新视图 六.视图的作用 总结 一、视图是什么? 视图是从一个或多个表中导出的虚拟表,它本身不存储数据,而是基于 SQL 查询的结果集。 二、特点 1.虚拟性࿱…...
标贝科技:大模型领域数据标注的重要性与标注类型分享
当前,大模型作为人工智能领域的前沿技术,其强大的泛化能力和复杂任务处理能力,依赖于海量数据的训练。而数据标注,作为连接原始数据与大模型训练的关键桥梁,在这一过程中发挥着举足轻重的作用。 大模型的训练依赖海…...
MYSQL备份恢复知识:第一章:备份操作举例
1. 备份工具 MySQL数据库的备份方式有两大类:一是物理备份,它对数据文件和日志进行整体备份;二是逻辑备份,通过DUMP工具将数据导出。具体的方法有以下几种: • 物理备份,MEB工具,是商用版本推荐…...
VS Code怎么设置python SDK路径
一、通过命令面板快速切换(推荐方法) 打开命令面板 • 快捷键:CtrlShiftP(Windows/Linux)或 CmdShiftP(macOS) • 输入命令:Python: Select Interpreter,回车后显示所有检…...
[经验总结]删除gitlab仓库分支报错:错误:无法推送一些引用到“http:”
问题描述 删除gitlab远程仓库报错。 [wingasowingaso release]$ git push gitlab --delete release remote: GitLab: You can only delete protected branches using the web interface. To http://x.x.x.x/gitlab/test.git! [remote rejected] release (pre-receive hoo…...
虹科干货 | CAN XL安全实践:深度防御下的密钥协商优化
摘要 随着汽车以太网的兴起和车载通信系统数量的增加,网络整合成为控制复杂性和成本的关键。当前架构呈现明确分层:以太网(100/1000Mbit/s)支撑信息娱乐、ADAS等高带宽应用,而CAN/CAN FD(0.5-5Mbit/s&#…...
Linux干货(一)
前言 从B站黑马程序员Linux课程摘选的学习干货,新手友好!若有侵权,会第一时间处理。 1.Linux目录结构 1.Linux操作系统的目录结构 Windows系统可以拥有多个盘符,如C盘、D盘、E盘 Linux没有盘符这个概念,只有一个根…...
Scala和Go差异
Scala和Go(又称Golang)是两种现代编程语言,各自具有独特的特性和设计哲学。 尽管它们都可以用于构建高性能、可扩展的应用程序,但在许多方面存在显著差异。 Scala和Go的详细比较,涵盖它们的异同点: 1. 语…...
PNG图片转icon图标Python脚本(简易版) - 随笔
摘要 在网站开发或应用程序设计中,常需将高品质PNG图像转换为ICO格式图标。本文提供一份高效Python解决方案,利用Pillow库实现透明背景完美保留的格式转换。 源码示例 from PIL import Imagedef convert_png_to_ico(png_path, ico_path, size):"…...
C语言中的宏
1.防止头文件重复包含 1.#pragma once #pragma once 是一个编译器指令,用于防止头文件被重复包含。它的核心作用是通过简单语法替代传统的头文件保护宏(#ifndef/#define/#endif),提升代码简洁性和可维护性。 作用详解 防止重复…...
飞拍技术介绍
运动控制探针功能详细介绍 运动控制探针功能详细介绍(CODESYS+SV63N伺服)_伺服探针功能-CSDN博客文章浏览阅读683次。文章浏览阅读1.2k次。本文详细介绍了如何使用汇川AM400PLC通过EtherCAT总线与禾川X3E伺服进行通信。包括XML硬件描述文件的下载与安装,EtherCAT总线的启用…...
Qt进阶开发:QTcpSocket的详解
文章目录 一、QTcpSocket 简介二、常用方法的介绍和使用三、常用的信号函数一、QTcpSocket 简介 QTcpSocket 是 Qt 网络模块中用于实现基于 TCP 协议的客户端通信的类。它提供了一个面向流的接口,允许程序通过套接字连接到远程主机,发送和接收数据。 所属模块:QtNetwork用于…...
React中的状态管理Dva总结
在 React 开发中,随着应用的复杂度增加,如何高效地管理应用状态成为了一个非常重要的问题。为了解决这一问题,很多开发者选择了 Redux,然而 Redux 的学习曲线较陡,且需要配置较多的样板代码。为此,Ant Desi…...
PyTorch中的nn.Embedding应用详解
PyTorch 文章目录 PyTorch前言一、nn.Embedding的基本原理二、nn.Embedding的实际应用简单的例子自然语言处理任务 前言 在深度学习中,词嵌入(Word Embedding)是一种常见的技术,用于将离散的词汇或符号映射到连续的向量空间。这种…...
Python Django基于模板的药品名称识别系统【附源码、文档说明】
博主介绍:✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇&…...
深度学习---获取模型中间层输出的意义
一、什么是 Hook(钩子函数)? 在 PyTorch 中,Hook 是一种机制,允许我们在模型的前向传播或反向传播过程中,插入自定义的函数,用来观察或修改中间数据。 最常用的 hook 是 forward hook…...
【软件测试】第一章·软件测试概述
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀软件测试与软件项目管理_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录…...
格雷希尔G10和G15系列自动化快速密封连接器,适用于哪些管件的密封,以及它们相关的特性有哪些?
格雷希尔G10和G15系列快速密封连接器,用于自动化和半自动化过程中的外部或内部密封,通过使用气压驱动来挤压内部的密封圈,创造一个适用于各种管件的无泄漏密封连接,连接器内部的弹性密封圈可以提供其他产品不能提供的卓越密封性能…...
从零实现一个高并发内存池 - 1
C 高性能内存池解析 在 C 开发中,内存管理一直是影响程序性能的关键因素之一。传统的内存分配方式如 malloc 和 free 在高并发场景下往往存在性能瓶颈。为了解决这一问题,很多优秀的内存池方案应运而生,其中 Google 的 tcmalloc(T…...
在 STM32 上使用 register 关键字
在 STM32 上使用 register 关键字时,有一些特别需要注意的事项。虽然 register 是 C 语言中的一个标准关键字,它用于提示编译器将变量尽可能存放在寄存器中,以加速访问,但在 STM32 这样的嵌入式平台上,还是需要考虑几个…...