Redis常用技術
阿新 • • 發佈:2018-11-18
container property connect cati tro nat add sco serialize
Xml配置:
<?xml version=‘1.0‘ encoding=‘UTF-8‘ ?> <!-- was: <?xml version="1.0" encoding="UTF-8"?> --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="50" /> <property name="maxTotal" value="100" /> <property name="maxWaitMillis" value="20000" /> </bean> <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" /> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="localhost" /> <property name="port" value="6379" /> <property name="poolConfig" ref="poolConfig" /> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="defaultSerializer" ref="stringRedisSerializer" /> <property name="keySerializer" ref="stringRedisSerializer" /> <property name="valueSerializer" ref="stringRedisSerializer" /> </bean> <bean id="redisMsgListener" class="com.ssm.chapter19.redis.listener.RedisMessageListener"> <property name="redisTemplate" ref="redisTemplate" /> </bean> <bean id="topicContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer" destroy-method="destroy"> <!--Redis連接工廠 --> <property name="connectionFactory" ref="connectionFactory" /> <!--連接池,這裏只要線程池生存,才能繼續監聽 --> <property name="taskExecutor"> <bean class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler"> <property name="poolSize" value="2" /> </bean> </property> <!--消息監聽Map --> <property name="messageListeners"> <map> <!--配置監聽者,key-ref和bean id定義一致 --> <entry key-ref="redisMsgListener"> <!--監聽類 --> <bean class="org.springframework.data.redis.listener.ChannelTopic"> <constructor-arg value="chat" /> </bean> </entry> </map> </property> </bean> </beans>
監聽類:
public class RedisMessageListener implements MessageListener { private RedisTemplate redisTemplate; @Override public void onMessage(Message message, byte[] bytes) { // 獲取消息 byte[] body = message.getBody(); // 使用值序列化器轉換 String msgBody = (String) getRedisTemplate().getValueSerializer().deserialize(body); System.err.println(msgBody); // 獲取channel byte[] channel = message.getChannel(); // 使用字符串序列化器轉換 String channelStr = (String) getRedisTemplate().getStringSerializer().deserialize(channel); System.err.println(channelStr); // 渠道名稱轉換 String bytesStr = new String(bytes); System.err.println(bytesStr); } public RedisTemplate getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } }
測試:
public class Chapter19Main { public static void main(String[] args) { testTransaction(); testPipeline(); testJedisPipeline(); testPubSub(); testExpire(); testLuaScript(); testRedisScript(); testLuaFile(); } public static void testTransaction() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> { ops.multi(); ops.boundValueOps("key1").set("value1"); // 註意由於命令只是進入隊列,而沒有被執行,所以此處采用get命令,而value卻返回為null String value = (String) ops.boundValueOps("key1").get(); System.out.println("事務執行過程中,命令入隊列,而沒有被執行,所以value為空:value=" + value); // 此時list會保存之前進入隊列的所有命令的結果 List list = ops.exec();// 執行事務 // 事務結束後,獲取value1 value = (String) redisTemplate.opsForValue().get("key1"); return value; }; // 執行Redis的命令 String value = (String) redisTemplate.execute(callBack); System.out.println(value); }
public static void testPipeline() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); // 使用Java8的Lambda表達式 SessionCallback callBack = (SessionCallback) (RedisOperations ops) -> { for (int i = 0; i < 100; i++) { int j = i + 1; ops.boundValueOps("pipeline_key_" + j).set("pipeline_value_" + j); ops.boundValueOps("pipeline_key_" + j).get(); } return null; }; long start = System.currentTimeMillis(); // 執行Redis的流水線命令 List resultList = redisTemplate.executePipelined(callBack); long end = System.currentTimeMillis(); System.err.println(end - start); } private static JedisPool getPool() { JedisPoolConfig poolCfg = new JedisPoolConfig(); // 最大空閑數 poolCfg.setMaxIdle(50); // 最大連接數 poolCfg.setMaxTotal(100); // 最大等待毫秒數 poolCfg.setMaxWaitMillis(20000); // 使用配置創建連接池 JedisPool pool = new JedisPool(poolCfg, "localhost"); // 從連接池中獲取單個連接 Jedis jedis = pool.getResource(); // 如果需密碼 // jedis.auth("password"); return pool; } public static void testJedisPipeline() { JedisPool pool = getPool(); Jedis jedis = pool.getResource(); long start = System.currentTimeMillis(); // 開啟流水線 Pipeline pipeline = jedis.pipelined(); // 這裏測試10萬條的讀寫2個操作 for (int i = 0; i < 100; i++) { int j = i + 1; pipeline.set("pipeline_key_" + j, "pipeline_value_" + j); pipeline.get("pipeline_key_" + j); } // pipeline.sync();//這裏只執行同步,但是不返回結果 // pipeline.syncAndReturnAll();將返回執行過的命令返回的List列表結果 List result = pipeline.syncAndReturnAll(); long end = System.currentTimeMillis(); // 計算耗時 System.err.println("耗時:" + (end - start) + "毫秒"); } public static void testPubSub() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); String channel = "chat"; redisTemplate.convertAndSend(channel, "I am lazy!!"); } public static void testExpire() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); redisTemplate.execute((RedisOperations ops) -> { ops.boundValueOps("key1").set("value1"); String keyValue = (String) ops.boundValueOps("key1").get(); Long expSecond = ops.getExpire("key1"); System.err.println(expSecond); boolean b = false; b = ops.expire("key1", 120L, TimeUnit.SECONDS); b = ops.persist("key1"); Long l = 0L; l = ops.getExpire("key1"); Long now = System.currentTimeMillis(); Date date = new Date(); date.setTime(now + 120000); ops.expireAt("key", date); return null; }); } public static void testLuaScript() { // 如果是簡單的對象,使用原來的封裝會簡易些 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); // 如果是簡單的操作,使用原來的Jedis會簡易些 Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection(); // 執行簡單的腳本 String helloJava = (String) jedis.eval("return ‘hello java‘"); System.out.println(helloJava); // 執行帶參數的腳本 jedis.eval("redis.call(‘set‘,KEYS[1], ARGV[1])", 1, "lua-key", "lua-value"); String luaKey = (String) jedis.get("lua-key"); System.out.println(luaKey); // 緩存腳本,返回sha1簽名標識 String sha1 = jedis.scriptLoad("redis.call(‘set‘,KEYS[1], ARGV[1])"); // 通過標識執行腳本 jedis.evalsha(sha1, 1, new String[] { "sha-key", "sha-val" }); // 獲取執行腳本後的數據 String shaVal = jedis.get("sha-key"); System.out.println(shaVal); // 關閉連接 jedis.close(); } public static void testRedisScript() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); // 定義默認腳本封裝類 DefaultRedisScript<Role> redisScript = new DefaultRedisScript<Role>(); // 設置腳本 redisScript.setScriptText("redis.call(‘set‘, KEYS[1], ARGV[1]) return redis.call(‘get‘, KEYS[1])"); // 定義操作的key列表 List<String> keyList = new ArrayList<String>(); keyList.add("role1"); // 需要序列化保存和讀取的對象 Role role = new Role(); role.setId(1L); role.setRoleName("role_name_1"); role.setNote("note_1"); // 獲得標識字符串 String sha1 = redisScript.getSha1(); System.out.println(sha1); // 設置返回結果類型,如果沒有這句話,結果返回為空 redisScript.setResultType(Role.class); // 定義序列化器 JdkSerializationRedisSerializer serializer = new JdkSerializationRedisSerializer(); // 執行腳本 // 第一個是RedisScript接口對象,第二個是參數序列化器 // 第三個是結果序列化器,第四個是Reids的key列表,最後是參數列表 Role obj = (Role) redisTemplate.execute(redisScript, serializer, serializer, keyList, role); // 打印結果 System.out.println(obj); } public static void testLuaFile() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class); // 讀入文件流 File file = new File("E:\\study_fold\\Java_EE_SSM\\ssm\\Chapter19\\src\\test.lua"); byte[] bytes = getFileToByte(file); Jedis jedis = (Jedis) redisTemplate.getConnectionFactory().getConnection().getNativeConnection(); // 發送文件二進制給Redis,這樣REdis就會返回sha1標識 byte[] sha1 = jedis.scriptLoad(bytes); // 使用返回的標識執行,其中第二個參數2,表示使用2個鍵 // 而後面的字符串都轉化為了二進制字節進行傳輸 Object obj = jedis.evalsha(sha1, 2, "key1".getBytes(), "key2".getBytes(), "2".getBytes(), "4".getBytes()); System.out.println(obj); } /** * 把文件轉化為二進制數組 * * @param file * 文件 * @return 二進制數組 */ public static byte[] getFileToByte(File file) { byte[] by = new byte[(int) file.length()]; try { InputStream is = new FileInputStream(file); ByteArrayOutputStream bytestream = new ByteArrayOutputStream(); byte[] bb = new byte[2048]; int ch; ch = is.read(bb); while (ch != -1) { bytestream.write(bb, 0, ch); ch = is.read(bb); } by = bytestream.toByteArray(); } catch (Exception ex) { ex.printStackTrace(); } return by; } }
輸出:
事務執行過程中,命令入隊列,而沒有被執行,所以value為空:value=null
value1
23
耗時:13毫秒
I am lazy!!
chat
chat
I am lazy!!
chat
chat
I am lazy!!
chat
chat
-1
hello java
lua-value
sha-val
731429de653665577edb661a6741c4083e103b77
com.ssm.chapter19.redis.pojo.Role@59474f18
2
Redis常用技術