<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
資料儲存在記憶體中,資料查詢速度快。可以分攤資料庫壓力。
查詢頻率比較高,修改頻率比較低。
安全係數低的資料
注意要將實體類實現序列化:
@Data @AllArgsConstructor @NoArgsConstructor @TableName(value = "tb_dept") public class Dept implements Serializable { @TableId(value = "id",type = IdType.AUTO) private Integer id; private String name; private String realname; }
對應依賴:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--連線資料來源--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--mp的依賴--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
controller層對應程式碼:
@RestController @RequestMapping("order") public class DeptController { @Resource private DeptService deptService; @GetMapping("getById/{id}") //order/getById/1 //{}可以放多個,由下面的傳參函數對應 //@PathVariable:獲取請求對映中{}的值 public Dept getById(@PathVariable Integer id){ return deptService.findById(id); } @GetMapping("deleteById/{id}") public String deleteById(@PathVariable Integer id){ int i = deptService.deleteById(id); return i>0?"刪除成功":"刪除失敗"; } @GetMapping("insert") public Dept insert(Dept dept){ Dept insert = deptService.insert(dept); return insert; } @GetMapping("update") public Dept update(Dept dept){ Dept update = deptService.update(dept); return update; } }
service層對應程式碼:
@Service public class DeptService { @Resource private DeptMapper deptMapper; //當儲存的value型別為物件型別使用redisTemplate //儲存的value型別為字串。StringRedisTemplate @Autowired private RedisTemplate redisTemplate; //業務程式碼 public Dept findById(Integer id){ ValueOperations forValue = redisTemplate.opsForValue(); //查詢快取 Object o = forValue.get("dept::" + id); //快取命中 if(o!=null){ return (Dept) o; } Dept dept = deptMapper.selectById(id); if(dept!=null){ //存入快取中 forValue.set("dept::"+id,dept,24, TimeUnit.HOURS); } return dept; } public int deleteById(Integer id){ redisTemplate.delete("dept::"+id); int i = deptMapper.deleteById(id); return i; } public Dept insert(Dept dept){ int insert = deptMapper.insert(dept); return dept; } public Dept update(Dept dept){ redisTemplate.delete("dept::"+dept.getId()); int i = deptMapper.updateById(dept); return dept; } }
設定源:
# 設定資料來源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
#sql紀錄檔
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#連線redis
spring.redis.host=192.168.22*.1**
spring.redis.port=6379
檢視的快取: 前部分程式碼相同@before通知,後部分程式碼也相同後置通知。 我們可以AOP完成快取程式碼和業務程式碼分離。
spring框架它應該也能想到。--使用註解即可完成。解析該註解。
(1)把快取的設定類加入
@Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解決查詢快取轉換異常的問題 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 設定序列化(解決亂碼的問題),過期時間600秒 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600)) //快取過期10分鐘 ---- 業務需求。 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//設定key的序列化方式 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) //設定value的序列化 .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager;
(2) 使用開啟快取註解
(3)使用註解
//業務程式碼 //使用查詢註解:cacheNames表示快取的名稱 key:唯一標誌---dept::key //先從快取中檢視key為(cacheNames::key)是否存在,如果存在則不會執行方法體,如果不存在則執行方法體並把方法的返回值存入快取中 @Cacheable(cacheNames = {"dept"},key="#id") public Dept findById(Integer id){ Dept dept = deptMapper.selectById(id); return dept; } //先刪除快取在執行方法體。 @CacheEvict(cacheNames = {"dept"},key = "#id") public int deleteById(Integer id){ int row = deptMapper.deleteById(id); return row; } //這個註釋可以確保方法被執行,同時方法的返回值也被記錄到快取中,實現快取與資料庫的同步更新。 @CachePut(cacheNames = "dept",key="#dept.id") public Dept update(Dept dept){ int insert = deptMapper.updateById(dept); return dept; }
使用壓測工具測試高並行下帶來執行緒安全問題
內部設定:
@RestController @RequestMapping("bucket") public class BucketController { @Autowired private BucketService bucketService; @GetMapping("update/{productId}") public String testUpdate(@PathVariable Integer productId){ String s = bucketService.updateById(productId); return s; } }
//此處寫就不需要在啟動類使用註解 @Mapper public interface BucketMapper extends BaseMapper<Bucket> { public Integer updateBucketById(Integer productId); }
@Data @AllArgsConstructor @NoArgsConstructor public class Bucket { @TableId(value = "productId",type = IdType.AUTO) private Integer productId; private Integer num; }
@Service public class BucketService { @Resource private BucketMapper bucketMapper; public String updateById(Integer productId){ //檢視該商品的庫存數量 Bucket bucket = bucketMapper.selectById(productId); if(bucket.getNum()>0){ //修改庫存每次減1 Integer integer = bucketMapper.updateBucketById(productId); System.out.println("扣減成功!剩餘庫存數:"+(bucket.getNum()-1)); return "success"; }else { System.out.println("扣減失敗!庫存數不足"); return "fail"; } } }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.qy151wd.dao.BucketMapper"> <update id="updateBucketById" parameterType="int"> update bucket set num=num-1 where productId=#{productId} </update> </mapper>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--連線資料來源--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--mp的依賴--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
我們看到同一個庫存被使用了n次。以及資料庫中庫存為負數。 執行緒安全問題導致。
對應的service層修改為
@Service public class BucketService { @Resource private BucketMapper bucketMapper; public String updateById(Integer productId){ //加自動鎖 synchronized (this){ //檢視該商品的庫存數量 Bucket bucket = bucketMapper.selectById(productId); if(bucket.getNum()>0){ //修改庫存每次減1 Integer integer = bucketMapper.updateBucketById(productId); System.out.println("扣減成功!剩餘庫存數:"+(bucket.getNum()-1)); return "success"; }else { System.out.println("扣減失敗!庫存數不足"); return "fail"; } } } }
如果搭建了專案叢集,那麼該鎖無效 。
(1)使用idea開叢集專案
(2)使用nginx
(3)測試結果
發現又出現: 重複數位以及庫存為負數。
(4)解決方法
service對應程式碼修改
@Service public class BucketService { @Resource private BucketMapper bucketMapper; @Autowired private RedisTemplate redisTemplate; public String updateById(Integer productId){ ValueOperations<String,String> forValue = redisTemplate.opsForValue(); Boolean flag = forValue.setIfAbsent("aaa::" + productId, "-----------------"); if(flag){ try{ //檢視該商品的庫存數量 Bucket bucket = bucketMapper.selectById(productId); if(bucket.getNum()>0){ //修改庫存每次減1 Integer integer = bucketMapper.updateBucketById(productId); System.out.println("扣減成功!剩餘庫存數:"+(bucket.getNum()-1)); return "success"; }else { System.out.println("扣減失敗!庫存數不足"); return "fail"; } }finally { redisTemplate.delete("aaa::"+productId); } } return "伺服器正忙,請稍後再試......."; } }
注意此處的測壓速度不易太快(推薦使用5秒100個執行緒)
經過測壓測試後,結果為:
到此這篇關於Java redis資料庫使用場景介紹的文章就介紹到這了,更多相關Java redis內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45