摘要:在查詢的服務(wù)方法上添加如下注解表明該方法的返回值需要緩存。當(dāng)被緩存的數(shù)據(jù)發(fā)生改變,緩存需要被清理或者修改,這里使用如下注解清除指定的緩存。事務(wù)是一個原子操作,所有的緩存,消息,這種非強(qiáng)一致性要求的操作,都應(yīng)該在事務(wù)成功提交后執(zhí)行。
【為什么使用redis
性能極高,redis能讀的速度是110000次/s,寫的速度是81000次/s
豐富的數(shù)據(jù)類型,redis支持二進(jìn)制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型操作
redis命令友好易用
springboot 已經(jīng)自動集成了redis
【redis配置1.首先在build.gradle中引入redis的依賴: compile("org.springframework.boot:spring-boot-starter-data-redis") 其實做完這一步我們已經(jīng)可以直接使用springboot提供的RedisTemplate,但是我們需要進(jìn)一步優(yōu)化,并且使用注解配置緩存 2.添加緩存配置類: - KeyGenerator表明我們自己定義key生成的策略 - RedisCustomSerializer表明我們自己定義序列化的方式,這里使用了protostuff來序列化,protostuff是目前最高效,節(jié)省空間的序列化方式 3.在springboot啟動類上表明啟用緩存:@EnableCaching 4.定義緩存的名稱集合,統(tǒng)一管理緩存名稱 5.在需要使用緩存的查詢服務(wù)上使用:@Cacheable(keyGenerator = "keyGenerator") 6.在需要清理緩存的業(yè)務(wù)服務(wù)上使用:@CacheEvict(keyGenerator = "keyGenerator")【緩存配置類
import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.lang.Nullable; import java.time.Duration; /** * redis緩存配置類 * @author ibm * @since 0 * @date 2018-4-12 */ @Configuration public class RedisConfig extends CachingConfigurerSupport { @Override @Nullable @Bean public KeyGenerator keyGenerator() { return new RedisCustomKeyGenerator(); } @Bean public RedisTemplate【自定義序列化redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); RedisCustomSerializer customSerializer = new RedisCustomSerializer(); template.setValueSerializer(customSerializer); template.afterPropertiesSet(); return template; } /** * 設(shè)置 redis 數(shù)據(jù)默認(rèn)過期時間 * 設(shè)置@cacheable 序列化方式 * @return */ @Bean public RedisCacheConfiguration redisCacheConfiguration(){ RedisCustomSerializer customSerializer = new RedisCustomSerializer(); RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer (customSerializer)).entryTtl(Duration.ofHours(1)); return configuration; } }
import com.example.seckill.dao.entity.KillProduct; import io.protostuff.LinkedBuffer; import io.protostuff.ProtostuffIOUtil; import io.protostuff.runtime.RuntimeSchema; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import org.springframework.lang.Nullable; /** * 自定義的redis序列化 * @author ibm * @since 0 * @date 2018-4-22 */ public class RedisCustomSerializer implements RedisSerializer { private final RuntimeSchema【自定義key生成策略schema = RuntimeSchema.createFrom(KillProduct.class); @Nullable @Override public byte[] serialize(@Nullable Object o) throws SerializationException { KillProduct killProduct = (KillProduct)o; byte[] bytes = ProtostuffIOUtil.toByteArray(killProduct,schema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE)); return bytes; } @Nullable @Override public Object deserialize(@Nullable byte[] bytes) throws SerializationException { if(bytes != null){ KillProduct killProduct = schema.newMessage(); //反序列化 ProtostuffIOUtil.mergeFrom(bytes,killProduct,schema); return killProduct; }else { return null; } } }
這里有一個不好的地方是我直接使用第一個參數(shù)作為key的標(biāo)示,是的程序中必須將id放在第一位,但這里只是一個事例,表明我們的key可以在這里進(jìn)行自定義。
import org.springframework.cache.interceptor.KeyGenerator; import java.lang.reflect.Method; /** * 自定義的redis緩存key生成策略 * @author ibm * @since 0 * @date 201804013 */ public class RedisCustomKeyGenerator implements KeyGenerator { /** * 簡單的指定生成killProduct的緩存id,這里可以根據(jù)業(yè)務(wù)類型自定義所有的key生成策略 * @param target 被調(diào)用方法的類實例 * @param method 方法的名稱 * @param params 方法的參數(shù) * @return 緩存key */ @Override public Object generate(Object target, Method method, Object... params) { return params[0]; } /** * 提供redisTemplate使用的key查詢方法 * @param cacheName 緩存名稱 * @return 緩存的key前綴 */ public static final String getKey4CacheName(String cacheName){ //spring在生成key的時候會用cacheName::的前綴 return cacheName + "::"; } }【使用spring注解操作緩存
在使用的類(讀與寫的類都需要)上我們使用如下注解表明這個服務(wù)使用緩存的名稱是什么,也可以直接在方法上指明cacheName但是要寫多次。
@CacheConfig(cacheNames = RedisCacheName.KILL_PRODUCT)
在查詢的服務(wù)方法上添加如下注解表明該方法的返回值需要緩存。
@Cacheable(keyGenerator = "keyGenerator")
當(dāng)被緩存的數(shù)據(jù)發(fā)生改變,緩存需要被清理或者修改,這里使用如下注解清除指定key的緩存。
@CacheEvict(keyGenerator = "keyGenerator")
使用redis-cli命令進(jìn)入redis(docker exec -it containerId redis-cli) 輸入keys * 查看所有的緩存 我們可以看見緩存是按照cacheName + "::" + id 的方式生成的,而我們的key生成策略也是針對于生成id的那一部分。【值得注意的一點
我們在使用緩存的時候應(yīng)該注意緩存的對象應(yīng)該處于哪一層,試想如果我的緩存在dao這一層,但是事務(wù)在service層,一個service方法包含了多個dao方法,如果在執(zhí)行service方法的時候,擁有緩存的dao方法成功,但是接下來的到方法失敗,那么我們的緩存就生效了,但是數(shù)據(jù)并沒有落庫,這就產(chǎn)生了數(shù)據(jù)不一致的問題。所以我們的緩存應(yīng)該在事務(wù)的更上層。事務(wù)是一個原子操作,所有的緩存,消息,這種非強(qiáng)一致性要求的操作,都應(yīng)該在事務(wù)成功提交后執(zhí)行。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69084.html
摘要:但是經(jīng)過測試自身的是次秒,是一個相當(dāng)不錯的數(shù)據(jù),所以我們這里將事務(wù)直接交給,使用存儲過程來降低行級鎖的持有時間。存儲過程代碼使用存儲過程之前必須保證數(shù)據(jù)庫已經(jīng)創(chuàng)建了存儲過程。表示使用在存儲過程中替代最后需要還原回來。 【什么是存儲過程 所謂的存儲過程是指:是一組為了完成特定功能的SQL語句集,經(jīng)編譯后存儲在數(shù)據(jù)庫中,用戶通過指定存儲過程的名字并給定參數(shù)(如果該存儲過程帶有參數(shù))來調(diào)用執(zhí)...
摘要:當(dāng)秒殺日期尚未達(dá)到會提示用戶秒殺尚未開始當(dāng)用戶多次秒殺同一商品會提示用戶重復(fù)秒殺當(dāng)秒殺日期過期或者秒殺商品的庫存為零會提示用戶秒殺結(jié)束。 【秒殺系統(tǒng)業(yè)務(wù)分析 在秒殺系統(tǒng)當(dāng)中有兩個核心的表:秒殺商品(kill_product)與秒殺明細(xì)(kill_item),具體的邏輯是一個用戶秒殺商品的庫存減一,秒殺明細(xì)的記錄增加一條。這兩步作是處于同一事務(wù)之中。 當(dāng)秒殺日期尚未達(dá)到會提示用戶秒殺尚...
閱讀 2255·2021-11-25 09:43
閱讀 3122·2021-10-14 09:42
閱讀 3484·2021-10-12 10:12
閱讀 1526·2021-09-07 10:17
閱讀 1900·2019-08-30 15:54
閱讀 3181·2019-08-30 15:54
閱讀 1550·2019-08-30 15:53
閱讀 1907·2019-08-29 11:21