源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

java高并发写入用户信息到数据库的几种方法

  • 时间:2021-08-12 13:38 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:java高并发写入用户信息到数据库的几种方法
假定存在这样一种情况 多个用户对数据库进行写,我们的业务逻辑规定,每个用户只能写一次,大部分用户也只发一次请求。
public void write(Uers u){ 
 // do something 
} 
但是有一种情况(1%的情况下吧)的就是有的用户会发两次甚至更多次写请求(因为数据库限制,我们不方便在主键上做文章)。 如果这个特殊的用户发送的两次请求时间间隔比较大,那就简单了,再每次写入的时候,写去数据库里看看,这个人有没有写过,如果已经写过了,就直接抛弃这个请求。
public void write(Uers u){ 
 if(!checkIfExistUser(u)){ 
   // do something 
  } 
} 
不过最大的问题就是,如果用户几乎在瞬时,发送了两个写操作。 而且假定我们的do something比较耗时,那么上面的策略就有可能失败。 为啥失败?我不用解释了吧。 那咋办? [b]方法一[/b] 万年不变的synchronized。
public synchronized void write(Uers u){ 
 if(!checkIfExistUser(u)){ 
   // do something 
  } 
} 
当然,我们得承认,有了上面的方法,就不会出现,数据库里有两条张三的记录了 但上面的锁的粒度太大了,张三写的时候,李四也不能写了。 其实我们想要的只是:张三自己本人,不能同时多次写入。 [b]方法二[/b] 类 String 维护一个字符串池。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。可见,当String相同时,String.intern()总是返回同一个对象,因此就实现了对同一用户加锁。由于锁的粒度局限于具体用户,使系统获得了最大程度的并发。
public synchronized void write(Uers u){ 
  synchronized(u.getUserId.intern()) { 
   // do something 
  } 
}
上面的思路就保证了张三写的时候,李四可以写,但是不能两个张三一块写。 [b]方法三[/b] 其实我个人觉得,方法二已经很好了,如果非要说方法二还有什么问题的话,只能说: String.inter()的缺陷是类 String 维护一个字符串池是放在JVM perm区的,如果用户数特别多,导致放入字符串池的String不可控,有可能导致OOM错误或者过多的Full GC。 那咋办?
public synchronized void write(Uers u){ 
  String userSuffix=getSuffix(u); 
  synchronized(userSuffix.intern()) { 
   // do something 
  } 
} 
至于那个获得后缀的策略,大家自己想。 有了这个策略,我就能保证1亿个用户,可能只有10000个不同的后缀。 有可能张三李四的后缀一样,但是张三李四同时发请求的概率,应该也不会太大。就算真的同时发了,那你等一下不行么? [b]方法四[/b]
Map locks = new Map();   
List lockKeys = new List();   
for(int number : 1 - 10000) {   
  Object lockKey = new Object();   
  lockKeys.add(lockKey);   
  locks.put(lockKey, new Object());   
}    
public void doSomeThing(String uid) {   
  Object lockKey = lockKeys.get(uid.hash() % lockKeys.size());   
  Object lock = locks.get(lockKey);   
  synchronized(lock) {   
   // do something   
  }   
} 
 
个人感觉和方法三的核心差不多。 [b]方法五[/b] 如果是集群情况下,两个张三几乎瞬时进入两台服务器,那java语言级别的锁都得报废。 可以使用redis的分布式锁 [b]方法六[/b] 使用zookeeper 只是听说有这么一个思路,但是本人没用过zookeeper,这个方法就不多说了。 以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持编程素材网!
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部