5年前,做的项目只在单机上运行,数据量不大,3大框架+一个数据库是标配
5年后,项目集群部署,数据量大,编程中要考虑分布式锁,分库,缓存等。
考虑项目时,需要加入新的元素,势必也会引入新的问题
现在开发中,哪些想法是标配呢?
#分布式锁
锁存在的意义是控制对共享资源的访问,共享资源主要有类变量、数据库、硬件资源等。现在编程中,类变量已经用的很少了
单机运行时,javaapi可以实现锁(允许同一时间只有一个方法在执行)
集群部署javaapi就无能为力,毕竟javaapi在不同机器或jvm上运行,两者没有联系
至于分布式锁的场景,
在编写的带有关键词synchronized的代码,严格意义上,基本都需要由分布式锁替代.在一般的大企业的应用中,基本都是集群部署。
基于分布式锁有3种实现方式:
1.基于数据库的锁机制
1.1 通过插入一条满足唯一性的记录实现分布式锁
1.2 通过数据库中预设的记录实现排他锁(for update-行级锁,前提是过滤的字段有唯一性索引,要不然就不能叫行级锁了)
springquartz就是通过这种方法实现的
这个是数据库悲观锁,其实还有一种乐观锁。比较典型的例子是svn提交,都可以提交,失败就回滚
2.基于缓存redis的锁机制
做的业务场景比较简单,所以很少用到redis锁,实在想不出分布式锁主要用在哪些地方。只能说贫(业)穷(务)限制了我对锁的想象力
锁->资源->数据库:什么数据库资源只能同时一个人访问,可能在秒杀活动能遇到(同一时间,万级别的人抢几件商品)
加锁:
public class RedisTool {
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
/**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @param expireTime 超期时间
* @return 是否获取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
解锁:
public class RedisTool {
private static final Long RELEASE_SUCCESS = 1L;
/**
* 释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
引用:
Redis 分布式锁的正确实现方式( Java 版 )
http://www.importnew.com/27477.html
3.基于zookeeper的锁机制
数据库锁:sql
redis锁:jedis api+redis服务器(
原理同数据库分布式锁)
zookeeper锁:curator api+zookeeper服务器
#缓存
对于一些简单的应用或场景或业务,直接查询数据库就能解决问题。再复杂一点也是用到第三方缓存组件
对于一些比较复杂的场景或业务,就要借助缓存服务器解决响应慢的问题
现在比较火的就是redis
在一般的企业级应用中,也就是用hashmap或list这样的类变量做为简单的缓存。就算是负载均衡部署,几个应用都从数据库中加载数据,只要数据不变也不会有多大问题。但是对于大型分布式应用,对数据的一致性要求比较高,这时候第三方缓存服务器就有用武之地了。
对于系统中,通过类变量hashmap或list来存储缓存数据的.用户量增加,分布式部署时,都可以通过redis替换
redis可用于解决tomcat启动过程中的session丢失问题
以获取最近25条评论为例
@Test
public void test0() {
String key = "latest.comments";
// 准备初始化数据
ListOperations<Serializable, Object> listOp = redisTemplate.opsForList();
for (int i = 1; i <= 100; i++) {
listOp.leftPush(key, i);
}
// 最近的25条记录
listOp.trim(key, 0, 25);
// 查询最近10条记录
int startPage = 3;
int nums = 10;
List<Object> list1 = listOp.range(key, (startPage - 1)*nums, startPage*nums -1);
if (null != list1 && list1.size() == nums) { // 全部在缓存中
for (int i = 0; i < list1.size(); i++) {
System.out.println(list1.get(i));
}
} else {
System.out.println("查询数据库获取历史记录");
}
}
#对外接口设计
对于一个有价(liu)值(liang)的业务,不仅要能提供直接浏览器访问,更需要提供可供其他系统调用的接口。怎么设计这些接口呢
2个层面考虑:
1.技术选型
http,hessian,netty,mq
2.流量控制
#配置文件
项目集群或分布式部署,配置文件中参数太多,重新部署太耗费时间或直接在运行项目中修改,地方太多。
更明确的方法是有一个配置管理系统
在spring项目中,通过覆盖属性配置类,启动应用时,调用配置系统设置参数。
#单点登录
#分库分表机制
可以从2个方面考虑:
1.DB集群配置
2.代码实现
spring环境中,多数据源的核心类是AbstractRoutingDataSource.
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DbRouterLocalContext.getDbKey();
}
}
获取当前环境数据源
public class DbRouterLocalContext {
private static final ThreadLocal<String> dbKeyLocal = new ThreadLocal<String>();
private static final ThreadLocal<String> tblKeyLocal = new ThreadLocal<String>();
public static void setDbKey (String dbIdx) {
dbKeyLocal.set(dbIdx);
}
public static String getDbKey() {
return dbKeyLocal.get();
}
public static void setTblKey (String tblIdx) {
tblKeyLocal.set(tblIdx);
}
public static String getTblKey() {
return tblKeyLocal.get();
}
}
当前环境使用数据库的配置,一般在dao层设置.根据传入的id或其他值
设置规则,应该传入哪个数据库。此时将涉及spring aop的编写
基本思路:
定义切面aspect,定义连接点pointcut(结合注解)
xml中配置:
数据库操作模板中,设置dyDataSource
<bean id="dyDataSource" class="com.byron.sharding.router.DynamicRoutingDataSource">
<property name="targetDataSources">
<map>
<entry key="db1" value-ref="dataSource01" />
<entry key="db2" value-ref="dataSource02" />
<entry key="db3" value-ref="dataSource03" />
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSource01" />
</bean>
参考:
http://flysoloing.github.io/2015/09/20/spring-database-sharding-practice/
#文件服务器
不要脱离业务学习技术,学习新技术同时学习新业务场景,即使这些场景你用不到
分享到:
相关推荐
《2018-2019年黑马最新版Java程序员面试宝典+题库pdf》是一份集合了近年来Java编程领域重点知识和面试常见问题的综合资源。这份资料主要针对初级Java程序员,旨在帮助他们巩固基础知识,掌握面试技巧,以便在求职...
Java程序员的辞职报告揭示了Java开发领域的一些常见挑战和职业发展问题。...总的来说,这份辞职报告为Java程序员的职业生涯提供了丰富的洞察,同时也为企业管理者提供了关于如何吸引和保留技术人才的思考。
【Java程序员辞职报告】\n\nJava程序员在2022年的辞职报告中反映了他们在IT行业中的工作体验、个人成长以及离职原因。报告通常包括以下几个关键知识点:\n\n1. **工作体验**:程序员在报告中提到在公司工作期间得到...
从这些辞职报告中,我们可以了解到Java程序员在职业道路上可能面临的挑战,以及他们在个人成长和职业选择方面的思考。这些报告也提醒我们,IT行业的工作不仅仅是编写代码,还包括沟通、协作和持续学习,以及如何平衡...
对于有3-5年经验的Java程序员,他们需要具备全面的技能集,包括但不限于Java核心技术、框架应用、数据库管理、分布式系统知识、性能优化等。同时,了解和掌握相关工具,如Spring Boot、MyBatis、Docker等,以及具备...
但是,一旦工作5年后,建议不要在跳了,更多是规划自己的职业生涯,程序员毕竟有“青春饭”的嫌疑,我们不能跟年轻人比呀。这时候如果想一直做技术,建议在一家好的公司长久呆下去,技术+业务,足够你混的了;如果想...
这篇文档包含了多个与Java程序员辞职相关的知识点,主要涉及职业发展、技术提升、薪资待遇、工作环境和公司文化: 1. **职业发展瓶颈**:程序员在工作中可能会遇到职业发展的停滞,当发现自身能力与期望的目标有较...
标题中的“四年Java 一个java程序员的年终总结”意味着这篇博文是一位有四年经验的Java开发者对他在编程领域中学习和工作的年度回顾。这样的总结通常涵盖了他在技术深化、项目经验、解决问题的方法以及职业成长等多...
由于社招通常针对有3-5年经验的开发者,面试问题更加侧重于实际技能和经验,而非死记硬背的技术点。以下将详细阐述这两个关键阶段的准备策略,以及Java程序员在学习过程中各阶段的建议。 **主语言本身及其高级特性*...
Java程序员面试题是一个涵盖广泛领域的主题,从基础语法到高级设计模式,再到系统架构和工程实践,每一个环节都是考察一个开发者综合素质的重要标准。这个"java程序员面试题汇总.7z"压缩包文件显然包含了从初级到...
对未来几年的职业规划,开发者计划深化业务知识,提升技术水平,期望在短期内成为独当一面的开发工程师,长期目标是成为具备系统架构能力的架构师。为了实现这些目标,设定的关键步骤包括自我复盘、强化优势、持续...
这个资源集合了2004年至2008年全年的程序员考试题目及其答案,涵盖了这五年间的上半年和下半年的考试内容。 在这五年的考试中,我们可以预见到涵盖的知识点广泛且深入,可能包括但不限于以下几个方面: 1. **基础...
在未来五年内,程序员需要掌握多种技能以适应不断变化的技术潮流和市场需求。以下是十项关键技能,涵盖编程语言、互联网 Rich Application、Web 开发、Web 服务、软实力、动态/函数编程语言、敏捷开发方法、开发修养...
在这个层级的程序员不仅仅关注技术本身,更多的是思考技术如何更好地服务于人类社会。他们是技术哲学的倡导者,通过思考技术伦理、人工智能的影响等问题,引领行业和社会的发展方向。 - **第8层**:创新者。创新者是...
Java编程语言自1995年发布以来,一直保持着其在软件开发领域的核心地位,尤其在企业级应用、安卓移动开发以及云计算服务等方面表现出色。本文将深入探讨Java编程的特点和技术,以帮助开发者更好地理解和应用这一强大...
《程序员2002-5期》这本杂志聚焦于当时IT行业的热点和发展,它包含了...总之,《程序员2002-5期》通过深度报道和专业解析,为当时的IT从业者提供了宝贵的行业信息和前瞻性思考,帮助他们紧跟技术潮流,提升专业技能。
- **市场需求变化**:紧跟市场趋势,解析当前企业在招聘时更看重哪些技能组合,并预测未来几年内技术岗位需求的变化方向。 - **自我定位思考**:引导读者思考自己在职业生涯中想要达到的目标,并结合行业发展趋势和...
### 如何像计算机科学家一样思考:Java版本 #### 书籍背景与目的 《如何像计算机科学家一样思考:Java版本》是一本由艾伦·唐尼(Allen B. Downey)编写的计算机科学入门教材,首次出版于1999年,并在之后经历了多...
1. 技术深度:程序员需要选择一个或几个技术领域进行深入学习,如Java、Python、C++或前端技术等。随着经验的积累,深入某一领域可以成为专家,例如架构师或技术顾问。 2. 技术广度:除了专业技能,了解其他相关...