日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

開始準備

開始之前我們需要有redis安裝,我們采用本機Docker運行Redis, 主要命令如下

docker pull redisdocker run --name my_redis -d -p 6379:6379 redisdocker exec -it my_redis bashredis-cli復制代碼

前面兩個命令是啟動redis docker, 后兩個是連接到docker, 在使用redis-cli 去查看redis里面的內容,主要查看我們存在redis里面的數(shù)據(jù)。

RedisTemplate

我們先從RedisTemplate開始,這個是最好理解的一種方式,我之前在工作中也使用過這種方式,先看代碼示例 我們先定義一個POJO類

@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class Book implements Serializable {private Long id;private String name;private String author;復制代碼

一個很簡單的BOOK類,三個字段: id,name和author. 再來一個RedisTemplate的Bean

@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);return template;復制代碼

再定義一個使用這個RedisTemplate的Service類

public Optional findOneBook(string name) {HashOperations HashOperations = redisTemplate.opsForHash();if (redisTemplate.hasKey(CACHE) && hashOperations.hasKey(CACHE, name)) {log.info("Get book {} from Redis.", name);return Optional.of(hashOperations.get(CACHE, name));Optional book = bookRepository.getBook(name);log.info("Book Found: {}", book);if (book.isPresent()) {log.info("Put book {} to Redis.", name);hashOperations.put(CACHE, name, book.get());redisTemplate.expire(CACHE, 10, TimeUnit.MINUTES);return book;復制代碼

我們使用Hash來存儲這個Book信息,在上面的方法中查找書名存不存在Redis中,如果存在就直接返回,如果不存在就去持久化存儲中找,找到就再通過Template寫入到Redis中, 這是緩存的通用做法。 使用起來感覺很方便。 我們這里為了簡單沒有使用持久化存儲,就硬編碼了幾條數(shù)據(jù), 代碼如下

@Repositorypublic class BookRepository {Map bookMap = new HashMap<>();public BookRepository(){bookMap.put("Apache kafka", Book.builder().name("apache kafka").id(1L).author("zhangsan").build());bookMap.put("Python/ target=_blank class=infotextkey>Python", Book.builder().name("python").id(2L).author("lisi").build());public Optional getBook(String name){if(bookMap.containsKey(name)){return Optional.of(bookMap.get(name));else{return Optional.empty();復制代碼

我們調用 bookService.findOneBook("python")和bookService.findOneBook("apache kafka"); 來把數(shù)據(jù)寫入到換存中

我們來看下存儲在Redis的數(shù)據(jù)長什么樣子。

127.0.0.1:6379> keys *1) "xacxedx00x05tx00x04book"127.0.0.1:6379> type "xacxedx00x05tx00x04book"hash127.0.0.1:6379> hgetall "xacxedx00x05tx00x04book"1) "xacxedx00x05tx00x06python"2) "xacxedx00x05srx00&com.ken.redistemplatesample.model.Book=x19x96xfbx7fx7fxdaxbex02x00x03Lx00x06authortx00x12LJAVA/lang/String;Lx00x02idtx00x10LJava/lang/Long;Lx00x04nameqx00~x00x01xptx00x04lisisrx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x00x00x00x00x00x02tx00x06python"3) "xacxedx00x05tx00x0capache kafka"4) "xacxedx00x05srx00&com.ken.redistemplatesample.model.Book=x19x96xfbx7fx7fxdaxbex02x00x03Lx00x06authortx00x12Ljava/lang/String;Lx00x02idtx00x10Ljava/lang/Long;Lx00x04nameqx00~x00x01xptx00bzhangsansrx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x00x00x00x00x00x01tx00x0capache kafka"復制代碼

我們可以看到數(shù)據(jù)被存在了key是“xacxedx00x05tx00x04book”的一個Hash表中, Hash里面有兩條記錄。 大家發(fā)現(xiàn)一個問題沒有? 就是這個key不是我們想象的用“book”做key,而是多了一串16進制的碼, 這是因為RedisTemplate使用了默認的JdkSerializationRedisSerializer 去序列化我們的key和value, 如果大家都用Java語言那沒有問題, 如果有人用Java語言寫,有人用別的語言讀,那就有問題,就像我開始的時候用hgetall "book"始終拿不到數(shù)據(jù)那樣。 RedisTemplate也提供了StringRedisTemplate來方便大家需要使用String來序列化redis里面的數(shù)據(jù)。簡單看下代碼


@Beanpublic StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;public Optional getBookString(String name){HashOperations hashOperations = stringRedisTemplate.opsForHash();if (stringRedisTemplate.hasKey(STRINGCACHE) && hashOperations.hasKey(STRINGCACHE, name)) {log.info("Get book {} from Redis.", name);return Optional.of(hashOperations.get(STRINGCACHE, name));Optional book = bookRepository.getBook(name);log.info("Book Found: {}", book);if (book.isPresent()) {log.info("Put book {} to Redis.", name);hashOperations.put(STRINGCACHE, name, book.get().getAuthor());stringRedisTemplate.expire(STRINGCACHE, 10, TimeUnit.MINUTES);return Optional.of(book.get().getAuthor());return Optional.empty();復制代碼

使用上就沒有那么方便,你就得自己寫需要存的是哪個字段,讀出來是哪個字段。

127.0.0.1:6379> keys *1) "string_book"127.0.0.1:6379> hgetall string_book1) "python"2) "lisi"3) "apache kafka"4) "zhangsan"復制代碼

如上圖所示,使用客戶端讀出來看起來就比較清爽一些。也可以看到占用的Size會小很多,我們這個例子相差7倍,如果是數(shù)據(jù)量大,這個還是比較大的浪費。

127.0.0.1:6379> keys *1) "xacxedx00x05tx00x04book"2) "string_book"127.0.0.1:6379> memory usage "string_book"(integer) 104127.0.0.1:6379> memory usage "xacxedx00x05tx00x04book"(integer) 712復制代碼JPA Repository

我們知道使用JPA Repository來訪問DataBase的時候,增刪改查那樣的操作能夠很方便的實現(xiàn),基本就是定義個接口,代碼都不用寫,Spring就幫我們完成了大部分的工作,那么訪問Redis是不是也可以這樣呢? 答案是肯定的,我們來看代碼 首先我們還是定義一個POJO

@RedisHash(value = "cache-book", timeToLive = 600)@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class CacheBook implements Serializable {@Idprivate Long userId;@Indexedprivate String name;private String author;復制代碼

這個類與我們上面template上面的類的區(qū)別就是我們加了兩個注解, 在類開頭加了 @RedisHash(value = "cache-book", timeToLive = 600) 在字段上面加了@Id和@Indexed 定義一個Repository的接口

public interface CacheBookRepository extends CrudRepository {Optional findOneByName(String name);復制代碼

再定義一個service和上面那個例子template一樣,緩存中有就到緩存中拿,沒有就到持久化存儲中找,并寫入緩存

@Slf4j@Servicepublic class BookService {private static final String CACHE = "repository-book";@Autowiredprivate CacheBookRepository cacheRepository;@Autowiredprivate BookRepository bookRepository;public Optional findOneBook(String name) {Optional optionalCacheBook = cacheRepository.findOneByName(name);if(!optionalCacheBook.isPresent())Optional book = bookRepository.getBook(name);log.info("Book Found: {}", book);if (book.isPresent()) {log.info("Put book {} to Redis.", name);cacheRepository.save(book.get());return book;return optionalCacheBook;復制代碼

代碼很簡單,簡單到不敢相信是真的。 還是一樣,調用這個方法,我們來看存在Redis里面的數(shù)據(jù)

127.0.0.1:6379> keys *1) "repository-book:2"2) "repository-book:2:idx"3) "repository-book"4) "repository-book:name:apache kafka"5) "repository-book:name:python"6) "repository-book:1:idx"7) "repository-book:1"復制代碼

哇,感覺存的內容有些多, 不用怕我們來看下各自存什么數(shù)據(jù) 首先看最短的一個

127.0.0.1:6379> smembers repository-book1) "1"2) "2"復制代碼

它里面存的是我們的id所有的value, 可以用來判斷id是否存在 再來看

127.0.0.1:6379> hgetall repository-book:21) "_class"2) "com.ken.redisrepositorysample.model.CacheBook"3) "author"4) "lisi"5) "name"6) "python"7) "userId"8) "2"復制代碼

這個是我們數(shù)據(jù)存放的地方

127.0.0.1:6379> smembers repository-book:1:idx1) "repository-book:name:apache kafka"127.0.0.1:6379> smembers "repository-book:name:apache kafka"1) "1"復制代碼

另外兩個都是set, 存在在它們里面的數(shù)據(jù)是索引信息。 由此可以看出通過JPA Repository 的方式,代碼很少,而且存儲的數(shù)據(jù)也很通用,個人覺得是比較理想的訪問方法。

Cache

我們已經(jīng)看了兩種方式,在訪問的時候遵循這樣的模式:緩存中有就從緩存中返回,沒有就從持久化存儲中找,然后寫入緩存,這部分代碼我也不想自己寫,那么Cache就是你的救星。 我們先看代碼 我們這次使用內存數(shù)據(jù)庫H2作為持久化存儲, 放一個schema.sql在resouces下面

drop table t_book if exists;create table t_book (id bigint auto_increment,create_time timestamp,update_time timestamp,name varchar(255),author varchar(200),primary key (id)insert into t_book (name, author, create_time, update_time) values ('python', 'zhangsan', now(), now());insert into t_book (name, author, create_time, update_time) values ('hadoop', 'lisi', now(), now());insert into t_book (name, author, create_time, update_time) values ('java', 'wangwu', now(), now());復制代碼

然后定義POJO

@Entity@Table(name = "T_BOOK")@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class CacheBook implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String author;@Column(updatable = false)@CreationTimestampprivate Date createTime;@UpdateTimestampprivate Date updateTime;復制代碼

完全是和數(shù)據(jù)庫綁定的代碼,和緩存沒有任何關系 一個Repository來訪問數(shù)據(jù)庫

public interface BookRepository extends JpaRepository {復制代碼

定義一個service來調用它

@Slf4j@Service@CacheConfig(cacheNames = "cache-book")public class BookService {@Autowiredprivate BookRepository bookRepository;@Cacheablepublic List findAllCoffee() {return bookRepository.findAll();@CacheEvictpublic void reloadCoffee() {復制代碼

這里就比較關鍵了,在類上加上了注解 @CacheConfig(cacheNames = "cache-book") 在方法上面加上了Cacheable和CacheEvict, Cacheable這個方法就是用來實現(xiàn)邏輯,有就從緩存中拿,沒有就從數(shù)據(jù)庫拿的,CacheEvict是調用這個方法的時候清除緩存。 然后再啟動入口程序的地方加上注解 @EnableJpaRepositories @EnableCaching(proxyTargetClass = true) 在配置文件Application.properties中加上

spring.jpa.hibernate.ddl-auto=nonespring.jpa.properties.hibernate.show_sql=truespring.jpa.properties.hibernate.format_sql=truemanagement.endpoints.web.exposure.include=*spring.cache.type=redisspring.cache.cache-names=cache-bookspring.cache.redis.time-to-live=600000spring.cache.redis.cache-null-values=falsespring.redis.host=localhost復制代碼

這樣就可以了, 感覺就是通過配置下就把緩存給完成了,非常的簡單 我們來看Redis中是怎么存的

127.0.0.1:6379> keys *1) "cache-book::SimpleKey []"127.0.0.1:6379> get "cache-book::SimpleKey []""xacxedx00x05srx00x13java.util.ArrayListxx81xd2x1dx99xc7ax9dx03x00x01Ix00x04sizexpx00x00x00x03wx04x00x00x00x03srx00(com.ken.rediscachesample.model.CacheBookxecxcbR=xe1Ux9bxf7x02x00x05Lx00x06authortx00x12Ljava/lang/String;Lx00ncreateTimetx00x10Ljava/util/Date;Lx00x02idtx00x10Ljava/lang/Long;Lx00x04nameqx00~x00x03Lx00nupdateTimeqx00~x00x04xptx00bzhangsansrx00x12java.sql.Timestamp&x18xd5xc8x01Sxbfex02x00x01Ix00x05nanosxrx00x0ejava.util.Datehjx81x01KYtx19x03x00x00xpwbx00x00x01x84xff]x85xb0xb-x81x80srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x00x00x00x00x00x01tx00x06pythonsqx00~x00bwbx00x00x01x84xff]x85xb0xb-x81x80sqx00~x00x02tx00x04lisisqx00~x00bwbx00x00x01x84xff]x85xb0xb<xbfxd8sqx00~x00x0bx00x00x00x00x00x00x00x02tx00x06hadoopsqx00~x00bwbx00x00x01x84xff]x85xb0xb<xbfxd8sqx00~x00x02tx00x06wangwusqx00~x00bwbx00x00x01x84xff]x85xb0xb<xbfxd8sqx00~x00x0bx00x00x00x00x00x00x00x03tx00x04javasqx00~x00bwbx00x00x01x84xff]x85xb0xb<xbfxd8x"復制代碼

看到?jīng)]有,就是當成Redis里面的String來存的, 如果數(shù)據(jù)量比較小,那是非常的方便,如果數(shù)據(jù)量大,這種方式就有些問題了。

總結

我們看了這三種方式,這里僅僅是做了個入門,每個里面都有很多細節(jié)的地方需要去研究和使用,整體的感覺是要想使用的簡單,那么存儲在Redis中的數(shù)據(jù)就要量少,量大后,就需要自己來定制了,那基本上要用RedisTemplate來做一些工作。

分享到:
標簽:Redis
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定