Android NFC标签 开发深度解析 触碰的艺术

亦余心之所善兮,虽九死其犹未悔。这篇文章主要讲述Android NFC标签 开发深度解析 触碰的艺术相关的知识,希望能为你提供帮助。
Jedis 是一个基于 java 语言的 Redis 客户端, 本文主要介绍使用 Jedis 访问 Redis 的一些基本方法。这里安装的 Redis 版本是 redis-5.0.4 稳定版。Redis 最广泛的应用场景就是使用它作为缓存, 除此还有网站访问统计、数据过期处理( 可以精确到毫秒) 、应用排行榜、分布式集群架构中的 session 分离等。
使用 Jedis 需要添加 Maven 依赖:

< !-- redis --> < dependency> < groupId> redis.clients< /groupId> < artifactId> jedis< /artifactId> < version> 2.10.2< /version> < /dependency>

1.Jedis的使用 1.xml配置方式 这里我们创建一个 Redis 操作的接口, 分别创建两个实现类对应 Redis 的单机版和集群版。当使用单机版 Redis 时, 配置单机版的实现类, 当使用集群版的时候, 配置集群版的实现类。
创建 JedisClient 接口:
public interface JedisClient { String set(String key, String value); String get(String key); }

分别创建实现类:
public class JedisClientSingle implements JedisClient { @ Autowired private JedisPool jedisPool; @ Override public String set(String key, String value) { Jedis jedis = jedisPool.getResource(); String result = jedis.set(key, value); jedis.close(); return result; } //省略get实现 }

public class JedisClientCluster implements JedisClient { @ Autowired private JedisCluster jedisCluster; @ Override public String set(String key, String value) { return jedisCluster.set(key, value); } //省略get实现 }

然后增加配置 resources/spring-config-cache-redis.xml( 单机版和集群版只能开一个) :
< ?xml version= " 1.0" encoding= " UTF-8" ?> < beans xmlns= " http://www.springframework.org/schema/beans" xmlns:xsi= " http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= " http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" > < !-- Redis连接池 --> < bean id= " jedisPoolConfig" class= " redis.clients.jedis.JedisPoolConfig" > < !-- 连接池最大连接数,使用负值表示没有限制,默认8 --> < property name= " maxTotal" value= " 8" /> < !-- 连接池中的最大空闲连接,默认8 --> < property name= " maxIdle" value= " 8" /> < !-- 连接池中的最小空闲连接,默认0 --> < property name= " minIdle" value= " 0" /> < !-- 是否开启jmx监控,可用于监控,默认true,建议开启 --> < property name= " jmxEnabled" value= " true" /> < !-- 当连接池用尽后,调用者是否要等待,只有当为true时,下面的maxWaitMillis才会生效,默认true,建议使用默认值 --> < property name= " blockWhenExhausted" value= " true" /> < !-- 当连接池用尽后,调用者最大阻塞等待时间,默认-1L表示永不超时 --> < property name= " maxWaitMillis" value= " 15000" /> < !-- 向连接池借用连接时是否做连接有效性检测(ping),无效连接会被移除,并尝试取出另一个,默认false,建议false --> < property name= " testOnBorrow" value= " false" /> < !-- 向连接池归还连接时是否做连接有效性检测(ping),无效连接会被移除,默认false,建议false --> < property name= " testOnReturn" value= " false" /> < !-- 在空闲时检查有效性,默认false --> < property name= " testWhileIdle" value= " true" /> < /bean> < !-- 配置Redis客户端单机版 --> < bean id= " jedisPool" class= " redis.clients.jedis.JedisPool" > < constructor-arg name= " poolConfig" ref= " jedisPoolConfig" /> < constructor-arg name= " host" value= " 127.0.0.1" /> < constructor-arg name= " port" value= " 6379" /> < constructor-arg name= " timeout" value= " 3000" /> < constructor-arg name= " password" value= " 123456" /> < /bean> < !-- 配置Redis客户端集群版 --> < !--< bean id= " jedisCluster" class= " redis.clients.jedis.JedisCluster" > < constructor-arg> < set> < bean class= " redis.clients.jedis.HostAndPort" > < constructor-arg index= " 0" name= " host" value= " 127.0.0.1" /> < constructor-arg index= " 1" name= " port" value= " 6379" /> < /bean> < bean class= " redis.clients.jedis.HostAndPort" > < constructor-arg index= " 0" name= " host" value= " 127.0.0.1" /> < constructor-arg index= " 1" name= " port" value= " 6380" /> < /bean> < bean class= " redis.clients.jedis.HostAndPort" > < constructor-arg index= " 0" name= " host" value= " 127.0.0.1" /> < constructor-arg index= " 1" name= " port" value= " 6381" /> < /bean> < /set> < /constructor-arg> < constructor-arg name= " connectionTimeout" value= " 3000" /> < constructor-arg name= " soTimeout" value= " 3000" /> < constructor-arg name= " maxAttempts" value= " 3" /> < constructor-arg name= " password" value= " 123456" /> < constructor-arg name= " poolConfig" ref= " jedisPoolConfig" /> < /bean> --> < !-- 配置Redis客户端实现类 --> < bean id= " redisClient" class= " com.example.server.soa.dao.redis.impl.RedisClientSingle" /> < !--< bean id= " redisClient" class= " com.example.server.soa.dao.redis.impl.RedisClientCluster" /> --> < /beans>

然后在项目启动类中导入配置即可:
@ SpringBootApplication @ ImportResource( " classpath:spring-config-cache-redis.xml" )

使用的时候当作普通的类注入就可以了:
@ Resource private JedisClient jedisClient;

2.连接池配置优化 1、选择适合的 maxTotal, 举个例子, 命令平均执行时间为 0.1ms = 0.001s, 如果业务需要 50000 QPS, 则 maxTotal 理论值 = 0.001 * 50000 = 50 个。实际设置时要偏大一些。
实际上对于 maxTotal 需要考虑的事情比较多, 大概有下面四点:
  • 业务希望 Redis 并发量;
  • 客户端执行命令时间;
  • Redis 资源, 例如 应用个数 * maxTotal 是不能超过 Redis 的最大连接数的( config get maxclients) ;
  • 资源开销, 例如 虽然希望控制空闲连接, 但是不希望因为连接池的频繁释放创建连接造成不必要的开销。
建议 maxIdle = maxTotal, 减少创建新连接的开销。
建议预热 minIdle, 减少第一次启动后的新连接开销。
2、常见问题与解决思路:
报错: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool …
Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
原因: 获取空闲连接的时候发生超时了。
报错: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool …
Caused by: java.util.NoSuchElementException: Pool exhausted
原因: 连接池里资源已经耗尽。
解决思路:
  1. 检查是否存在慢查询阻塞, 连接池连接都被 hang 住了;
  2. 检查是否存在资源池参数不合理, 例如 QPS 高、连接池小;
  3. 检查是否存在连接泄露( 没有 close()) , 此类问题比较难定位, 例如 client list、netstat 等, 最重要的是代码;
  4. 检查是否存在 DNS 异常等。
2.基于Redis实现分布式应用限流 限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统, 一旦达到限制速率则可以拒绝服务。实际场景中常用的限流策略:
  • nginx接入层限流: 按照一定的规则如帐号、IP、系统调用逻辑等在Nginx层面做限流。
  • 业务应用系统限流: 通过业务代码控制流量这个流量可以被称为信号量, 可以理解成是一种锁, 它可以限制一项资源最多能同时被多少进程访问。
  • 数据库限流: 红线区, 力保数据库。
【Android NFC标签 开发深度解析 触碰的艺术】通过业务应用系统限流实现方案参考: https://my.oschina.net/giegie/blog/1525931

    推荐阅读