คำนำ
สปริงห่อหุ้มเทมเพลตที่ค่อนข้างทรงพลังเพื่อใช้งานง่ายในการใช้ Redis; ฉันใช้ Redis ในระบบนิเวศฤดูใบไม้ผลิมาก่อน แต่ใช้เจไดโดยตรงสำหรับการโต้ตอบที่สอดคล้องกัน ทีนี้ลองมาดูกันว่าใช้งาน Redistemplate อย่างไรและใช้งานได้ง่ายกว่าหรือไม่
Jedis ยังคงใช้สำหรับการจัดการกลุ่มการเชื่อมต่อดังนั้นนอกเหนือจากการแนะนำ Spring-Data-redis รวมถึงการพึ่งพา Jedis แล้วเพิ่มไฟล์ POM
<การพึ่งพา> <roupId> org.springframework.data </groupId> <ratifactid> Spring-Data-Redis </artifactid> <sersion> 1.8.4.release </Side> </Serpercy>
หากคุณต้องการระบุพารามิเตอร์ที่เกี่ยวข้องกับอนุกรมคุณสามารถแนะนำแจ็คสันได้ บทความนี้เป็นระดับเริ่มต้นง่าย ๆ ดังนั้นคุณจะไม่เพิ่มสิ่งนี้
เตรียมพารามิเตอร์การกำหนดค่าที่เกี่ยวข้องกับ REDIS พารามิเตอร์ทั่วไปรวมถึงโฮสต์, พอร์ต, รหัสผ่าน, หมดเวลา .... ต่อไปนี้เป็นการกำหนดค่าอย่างง่ายและให้ความหมายที่สอดคล้องกัน
redis.hostname = 127.0.0.1redis.port = 6379Redis.password = https: //blog.hhui.top# การเชื่อมต่อหมดเวลา redis.timeout = 10,000#หมายเลขว่างสูงสุด redis.maxidle = 300#ควบคุม หากเป็น Jedis 2.4 ให้ใช้คุณสมบัตินี้กับ Redis.maxtotal = 1,000#การเชื่อมต่อสูงสุดเวลารอเวลารอ หากเวลานี้เกินเวลานี้จะได้รับข้อยกเว้น ตั้งค่าเป็น -1 หมายถึงไม่มีขีด จำกัด redis.maxwaitmillis = 1000#เวลาว่างขั้นต่ำของการเชื่อมต่อคือค่าเริ่มต้น 18000000ms (30 นาที) Redis.MinevictableidletItimeLis = 300000#จำนวนการเชื่อมต่อสูงสุดจะถูกปล่อยออกมาในแต่ละครั้ง ค่าเริ่มต้น -1Redis.timeBetweeneVictionRunsmillis = 30000# ไม่ว่าจะตรวจสอบก่อนที่จะลบการเชื่อมต่อออกจากพูลหากการตรวจสอบล้มเหลวให้ลบการเชื่อมต่อออกจากพูลและพยายามลบ redis.testonborrow = true# ตรวจสอบความถูกต้องเมื่อไม่ได้ใช้งาน
อธิบาย
โปรดอย่าลืมตั้งรหัสผ่าน Redis โดยเฉพาะอย่างยิ่งเมื่ออนุญาตให้เข้าถึงระยะไกล หากคุณไม่มีรหัสผ่านหมายเลขพอร์ตเริ่มต้นจะถูกสแกนและฉีดลงในสคริปต์ได้ง่ายแล้วเริ่มขุดเพื่อคน (ประสบการณ์ส่วนตัว ... )
ตามแนวคิดทั่วไปก่อนอื่นคุณต้องโหลดการกำหนดค่าข้างต้นสร้างพูลการเชื่อมต่อ Redis จากนั้นสร้างอินสแตนซ์วัตถุ Redistemplate และในที่สุดก็ถือความแข็งแกร่งนี้เพื่อเริ่มการอ่านและเขียนต่างๆ
ใช้ javaconfig เพื่อกำหนดค่าส่วนใหญ่สองถั่วอ่านไฟล์กำหนดค่าเพื่อตั้งค่าพารามิเตอร์ต่าง ๆ และ redistemplate ที่คาดหวัง
@configuration @propertySource ("classpath: redis.properties") คลาสสาธารณะ redisconfig ขยาย jcacheconfigurersupport {@autowired สภาพแวดล้อมส่วนตัว @Bean สาธารณะ redisconnectionFactory redisconnectionFactory () {jedisconnectionFactory fac = new JedisconnectionFactory (); fac.sethostname (Environment.getProperty ("Redis.hostname")); fac.setport (integer.parseint (Environment.getProperty ("redis.port"))); fac.setPassword (environment.getProperty ("redis.password")); fac.settimeout (integer.parseint (environment.getProperty ("redis.timeout"))); fac.getPoolConfig (). setMaxidle (integer.parseint (environment.getProperty ("redis.maxidle")))); fac.getPoolConfig (). setMaxtotal (integer.parseint (environment.getProperty ("redis.maxtotal")))); fac.getpoolconfig (). setmaxwaitmillis (integer.parseint (Environment.getProperty ("redis.maxwaitmillis"))); fac.getPoolConfig (). SetMineVictableidletItimeMillis (Integer.ParseInt (Environment.getProperty ("Redis.MinevictableidletItimeMillis")))); fac.getPoolConfig (). setMinevictableidletEtimeLis "))); fac.getPoolConfig (). setMinevictableidletItimeLis (Integer.ParseInt (Environment.getProperty .SetNumtestsperevictionRun (Integer.parseint (Environment.getProperty ("Redis.numtestsperevictionRun")); fac.getpoolconfig (). Settestonborw (Boolean.parseboolean (สิ่งแวดล้อม GetProperty ("Redis.testonborw")); Redistemplate (redisconnectionfactory redisconnectionfactory) {redistemplate <string, string> redis = ใหม่ redistemplate <> (); @runwith (springjunit4classrunner.class) @contextconfiguration (classes = {redisconfig.class}) คลาสสาธารณะ redistest {@autowired ส่วนตัว redistemplate <สตริงสตริง> redistemplate; @Test โมฆะสาธารณะ testRedIsObj () {แผนที่ <สตริง, วัตถุ> คุณสมบัติ = new hashmap <> (); Properties.put ("123", "Hello"); Properties.put ("ABC", 456); redistemplate.opsforhash (). putall ("แฮช", คุณสมบัติ); MAP <Object, Object> Ans = redistemplate.opSforHash (). รายการ ("แฮช"); System.out.println ("Ans:" + Ans); -หลังจากดำเนินการแล้วเอาต์พุตมีดังนี้
ตอบ: {123 = สวัสดี, abc = 456}การตัดสินจากการกำหนดค่าข้างต้นและการใช้งานมันง่ายมาก โดยพื้นฐานแล้วไม่มีวงกลมอยู่รอบ ๆ แต่เมื่อคุณเชื่อมต่อกับ Redis-cli คุณไม่สามารถสอบถามเนื้อหาของคีย์แฮชได้
127.0.0.1:6379> รับแฮช (ไม่มี) 127.0.0.1:6379> คีย์ *1) "/xac/xed/x00/x05t/x00/x04hash"
ไม่มีปัญหาในการใช้รหัสเพื่อตรวจสอบ ฉันเชื่อมต่อคอนโซลโดยตรงและพบว่าคีย์นี้แตกต่างจากสิ่งที่เราคาดหวังไว้กับคำนำหน้าทำไม?
เพื่อที่จะแก้ปัญหาข้างต้นฉันสามารถแก้ไขข้อบกพร่องและดูว่าเกิดอะไรขึ้น
ตำแหน่งซอร์สโค้ดที่สอดคล้องกันตำแหน่ง:
// org.springframework.data.redis.core.abstractoperations#rawkeybyte [] rawkey (คีย์วัตถุ) {assert.notnull (คีย์, "คีย์ที่ไม่เป็นโมฆะ"); ส่งคืนสิ่งนี้ keyserializer () == null && key instanceof byte []? (byte []) ((byte []) คีย์): this.keyserializer (). serialize (คีย์);}คุณจะเห็นได้ว่าคีย์นี้ไม่ใช่ key.getBytes () ที่เราคาดหวัง แต่นี่คือเรียกว่านี่คือ serialize (คีย์) ผลลัพธ์ของการดีบักคือ serializer เริ่มต้นคือ jdkserializationredisserializer
จากนั้นทำตามเบาะแสและก้าวไปทีละขั้นตอนลิงค์มีดังนี้
// org.springframework.core.serializer.serializingConverter#แปลง // org.springframework.core.serializer.defaultSerializer#serializepublic refitearserializer ioexception {ถ้า (! (วัตถุอินสแตนซ์ของ serializable)) {โยน unlegalargumentException ใหม่ (this.getClass (). getSimplename () + "ต้องใช้ payload แบบ serializable แต่ได้รับวัตถุประเภท [" + Object.getClass () getName () + "]") } else {objectOutputStream objectOutputStream = new ObjectOutputStream (outputStream); ObjectOutputStream.writeObject (วัตถุ); ObjectOutputStream.flush (); -ดังนั้นการใช้งานที่เฉพาะเจาะจงจึงชัดเจนมากซึ่งเป็น ObjectOutputStream สิ่งนี้เป็นเครื่องมือสตรีมมิ่ง Deserial Serialial ดั้งเดิมใน Java มันจะมีข้อมูลประเภทดังนั้นมันจะติดตั้งคำนำหน้า
ดังนั้นเพื่อแก้ปัญหานี้มันชัดเจนขึ้น แทนที่ jdkserializationredisserializer ดั้งเดิมและเปลี่ยนเป็นสตริงซึ่งเพียงแค่ให้ stringredisserializer ดังนั้นในการกำหนดค่าของ redistemplate ให้แก้ไขเล็กน้อย
@BeanPublic redistemplate <String, String> Redistemplate (redisconnectionFactory redisconnectionFactory) {redistemplate <string, string> redis = ใหม่ redistemplate <> (); Redis.SetConnectionFactory (RedisconnectionFactory); // ตั้งค่าวิธีการทำให้เป็นอนุกรมเริ่มต้นของสตริง redis/ค่า stringredisserializer stringredisserializer = ใหม่ stringredisserializer (); redis.setKeyserializer (Stringredisserializer); redis.setValueserializer (Stringredisserializer); redis.sethashkeyserializer (Stringredisserializer); redis.sethashvalueserializer (Stringredisserializer); redis.AfterPropertiesset (); return redis;}ดำเนินการอีกครั้งและสิ่งที่น่าอับอายเกิดขึ้นข้อยกเว้นถูกโยนลงไปและการแปลงประเภทล้มเหลว
java.lang.classcastexception: java.lang.integer ไม่สามารถส่งไปที่ java.lang.string ที่ org.springframework.data.redis.serializer.stringredisserializer.serialize org.springframework.data.redis.core.abstractoperations.rawhashvalue (Abstractoperations.java:171) ที่ org.springframework.data.core.defaulthashoperations.putall
เมื่อดูที่กรณีทดสอบก่อนหน้าค่าในแผนที่มีจำนวนเต็มและพารามิเตอร์ที่ได้รับจาก Stringredisserializer ต้องเป็นสตริงดังนั้นอย่าใช้สิ่งนี้และคุณจะยังคงเขียนที่เข้ากันได้
คลาสสาธารณะ DEFAINTSTRSERIALIZER ใช้ REDISSERIALIAZ <POCICT> {charset สุดท้ายส่วนตัว Public DefaultStrSerializer () {this (charset.forname ("UTF8")); } สาธารณะ defaultStrSerializer (charset charset) {assert.notnull (charset, "charset ต้องไม่เป็นโมฆะ!"); this.charset = charset; } @Override ไบต์สาธารณะ [] serialize (Object O) พ่น SerializationException {return o == null? null: string.valueof (o) .getBytes (charset); } @Override วัตถุสาธารณะ deserialize (byte [] bytes) โยน serializationException {return bytes == null? NULL: สตริงใหม่ (ไบต์, charset); -จากนั้นคุณสามารถเริ่มสนุกและทดสอบหลังจากดำเนินการ
ปุ่ม *1) "/xac/xed/x00/x05t/x00/x04hash" 2) "แฮช" 127.0.0.1:6379> hgetall hash1) "123" 2) "สวัสดี" 3) "abc" 4) "456"
เรามาดูท่าทางการใช้งานของ redistemplate สั้น ๆ และอ่านและห่อหุ้มวิธีการเรียกใช้โดย OpsFoRXXX สำหรับโครงสร้างข้อมูลที่แตกต่างกัน (สตริง, รายการ, ZSET, แฮช)
// hash data โครงสร้างการทำงาน org.springframework.data.redis.core.redistemplate#opsforhash // listorg.springframework.data.redis.core.redistemplate#opsforlist // stringorg.springframework.data.data.data.data setorg.springframework.data.redis.core.redistemplate#opsforzset
นอกเหนือจากวิธีการใช้งานข้างต้นแล้วอีกวิธีหนึ่งคือการใช้งานโดยตรง กรณีง่าย ๆ มีดังนี้
@TestPublic เป็นโมฆะ testredis () {String key = "Hello"; ค่าสตริง = "โลก"; redistemplate.execute ((rediscallback <void>) con -> {con.set (key.getBytes (), value.getBytes ()); return null;}); สตริง asn = redistemplate.execute ((rediscallback <string>) con -> สตริงใหม่ (con.get (key.getBytes ()))); System.out.println (asn); String hkey = "hkey"; redistemplate.execute ((rediscallback <void>) con -> {con.hset (hkey.getBytes (), "23" .getBytes (), "อะไร" .getBytes ()); return null;}); แผนที่ <byte [], byte []> map = redistemplate.execute ((rediscallback <map <byte [], byte []>) con -> con.hgetall (hkey.getBytes ())); สำหรับ (map.entry <byte [], byte [] >> รายการ: map.entryset ()) {system.out.println ("คีย์:" + สตริงใหม่ (entry.getKey ()) + "|" + สตริงใหม่ (entry.getValue ())); -ผลลัพธ์ผลลัพธ์มีดังนี้
โลก
คีย์: 23 | ค่า: อะไร
คำถามที่สามารถคิดได้ว่าเป็นธรรมชาติคือความแตกต่างระหว่างสองวิธีข้างต้นคืออะไร?
เลเยอร์พื้นฐานของ OpsFoRXXX ทำได้โดยการเรียกใช้งาน ส่วนใหญ่จะห่อหุ้มท่าทางการใช้งานและกำหนดอนุกรมซึ่งทำให้ง่ายขึ้นและสะดวกกว่าในการใช้งาน ด้วยวิธีนี้ทรัมเป็ตขนาดเล็กคือจำเป็นต้องสร้างวัตถุ defaultxxxxoperations ใหม่ทุกครั้งและใช้เวลาอีกหนึ่งขั้นตอน จากสิ่งนี้มันจะนำประสิทธิภาพและหน่วยความจำเพิ่มเติมหรือไม่? ฉันไม่ได้ทดสอบ แต่โดยส่วนตัวแล้วฉันรู้สึกว่าปริมาณมีขนาดเล็กไม่ควรมีผลกระทบอย่างชัดเจน และเมื่อ QPS สูงมากความช่วยเหลือในการเพิ่มประสิทธิภาพที่สะดวกนี้สามารถนำมาได้นั้นอาจไม่มากนัก
การศึกษา-เดโม/สปริง-เรดดิส
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com