㈠ redis 存儲java對象是json字元串還是序列化
如果是數據完全可以使用JSON方式。畢竟redis直接set、get使用起
來門檻低很多。redis是沒有提供專用的設置對象方法,需要自己進行改寫。如果是擔心JSON轉對象會消耗資源的情況,這個問題需要考量幾個地方,第一
點:就是使用的JSON轉換lib是否就會存在性能問題。第二點:就是數據的數據量級別,如果是存儲百萬級的大數據對象,建議採用存儲序列化對象方式。如
果是少量的數據級對象,或者是數據對象欄位不多,還是建議採用JSON轉換成String方式。畢竟redis對存儲字元類型這部分優化的非常好。具體采
用的方式與方法,還要看你所使用的場景。
㈡ 如何用redis來生成唯一Id
構造方法一:
public RedisAtomicLong(java.lang.String redisCounter,
RedisConnectionFactory factory)
1
2
1
2
該實例對應的自動增長的主鍵的key的名字為為redisCounter,如果redis中存在key的name為redisCounter的鍵值對,那麼,則取其值;否則,將redisCounter對應的key值設置為0;
構造方法二:
public RedisAtomicLong(java.lang.String redisCounter,
RedisConnectionFactory factory,
long initialValue)
1
2
3
1
2
3
創建一個新的RedisAtomicLong實例,該實例對應的自動增長的主鍵的key的名字為為redisCounter,並將key name為redisCounter的值設置為initialValue;
RedisAtomicLong類有以下幾個主要的方法:
方法一:
public long get();//返回當前的值
1
1
方法二:
public void set(long newValue);//設置當前實例的值為newValue
1
1
方法三:
public long incrementAndGet();//將當前實例的key值加一並且返回
1
1
那麼,我們如何獲得一個RedisAtomicLong實例呢?樓主提供以下兩個方法:
在獲取實例之前,我們需要設置好jedis的配置。
在application.xml文件中,加入以下配置:
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxTotal}" />
<property name="maxIdle" value="${redis.pool.maxIdle}" />
<property name="testOnBorrow" value="${redis.pool.testOnBorrow}" />
</bean>
<!-- jedis伺服器配置 -->
<bean id="jedisShardInfo" class="redis.clients.jedis.JedisShardInfo">
<constructor-arg index="0" value="${redis.ip}" />
<constructor-arg index="1" value="${redis.port}" type="int" />
</bean>
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.ip}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="jedisPoolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnFactory"/>
<property name="keySerializer" ref="keySerializer"/>
<property name="enableTransactionSupport" value="false"/>
</bean>
<!-- redis 序列化-->
<bean id="keySerializer"
class="org.springframework.data.redis.serializer.StringRedisSerializer" />
㈢ redis 存儲java對象是json字元串還是序列化
是進行序列化存儲的。
Redis存儲對象時,要對這個對象進行序列化。序列化還有一個作用是可以將對象序列化之後通過socket進行傳輸。那麼,JSON也是一個進行數據交換的格式。何不將對象轉為JSON字元串然後當作String存在Value中也是可以的。
㈣ redis中為什麼要序列化key
如果是數據完全可以使用JSON方式。畢竟redis直接set、get使用起來門檻低很多。redis是沒有提供專用的設置對象方法,需要自己進行改寫。如果是擔心JSON轉對象會消耗資源的情況,這個問題需要考量幾個地方,第一點:就是使用的JSON轉換lib是否就會存在性能問題。第二點:就是數據的數據量級別,如果是存儲百萬級的大數據對象,建議採用存儲序列化對象方式。如果是少量的數據級對象,或者是數據對象欄位不多,還是建議採用JSON轉換成String方式。畢竟redis對存儲字元類型這部分優化的非常好。具體採用的方式與方法,還要看你所使用的場景。
㈤ redis怎麼序列化
redis序列化數據有多重方式:
JacksonJsonRedisSerializer
OxmSerializer
這里前兩種測試
1.StringSerializer.java
2.測試類
㈥ java開發中如何巧妙的使用Redis提高性能
樓主您好
把Redis作為緩存,將一些熱點數據放到Redis中,讀取時先讀redis,載讀db。
至於減少內存,注意:Redis中數據的過期策略;選擇合適的數據結構,例如:選擇hash而非string;數據存儲進redis前使用序列化工具壓縮,推薦MsgPack。
推薦知乎:https://www.hu.com/question/29548367
㈦ redis消息隊列還有其他嗎
基於Redis消息隊列-實現簡訊服務化
1.Redis實現消息隊列原理
常用的消息隊列有RabbitMQ,ActiveMQ,個人覺得這種消息隊列太大太重,本文介紹下基於Redis的輕量級消息隊列服務。
一般來說,消息隊列有兩種模式,一種是發布者訂閱模式,另外一種是生產者和消費者模式。Redis的消息隊列,也是基於這2種原理的實現。
發布者和訂閱者模式:發布者發送消息到隊列,每個訂閱者都能收到一樣的消息。
生產者和消費者模式:生產者將消息放入隊列,多個消費者共同監聽,誰先搶到資源,誰就從隊列中取走消息去處理。注意,每個消息只能最多被一個消費者接收。
2.Redis消息隊列使用場景
在我們的項目中,使用消息隊列來實現簡訊的服務化,任何需要發送簡訊的模塊,都可以直接調用簡訊服務來完成簡訊的發送。比如用戶系統登錄注冊簡訊,訂單系統的下單成功的簡訊等。
3.SpringMVC中實現Redis消息隊列
因為我們簡訊只需要發送一次,所以我們使用的是消息隊列的生產者和消費者模式。
3.1引入Maven依賴
引入Redis相應的maven依賴,這里需要spring-data-redis和jedis
//pom.xml <dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.0.RELEASE</version>
</dependency>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.5.1</version>
</dependency>12345678910111213
3.2配置redis生成者消費者模式
//applicationContext-redis.xml <?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:redis="http://www.springframework.org/schema/redis"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-34.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis-1.0.xsd">
<description>spring-data-redis配置</description>
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"></property>
<property name="port" value="${redis.port}"></property>
<property name="usePool" value="true"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory"></property>
</bean>
<bean id="jdkSerializer"
class="org.springframework.data.redis.serializer." />
<bean id="smsMessageListener"
class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="smsMessageDelegateListener" />
<property name="serializer" ref="jdkSerializer" />
</bean>
<bean id="sendMessage" class="com.djt.common.cache.redis.queue.SendMessage">
<property name="redisTemplate" ref="redisTemplate"/>
</bean>
<redis:listener-container>
<redis:listener ref="smsMessageListener" method="handleMessage"
serializer="jdkSerializer" topic="sms_queue_web_online" />
</redis:listener-container>
<!-- jedis -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="300" /> <!-- 最大能夠保持idel狀態的對象數 -->
<property name="maxTotal" value="60000" /> <!-- 最大分配的對象數 -->
<property name="testOnBorrow" value="true" /> <!-- 當調用borrow Object方法時,是否進行有效性檢查 -->
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="${redis.host}" />
<constructor-arg index="2" value="${redis.port}" type="int" />
</bean></beans>
主要的配置說明:
1.序列化:一般我們向Redis發送一個消息定義的Java對象,這個對象需要序列化。這里使用:
<bean id="jdkSerializer" class="org.springframework.data.redis.serializer." />1
2.發送者:
<bean id="sendMessage" class="com.djt.common.cache.redis.queue.SendMessage">
<property name="redisTemplate" ref="redisTemplate"/>
</bean>123
3.監聽者:
<bean id="smsMessageListener"
class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="smsMessageDelegateListener" />
<property name="serializer" ref="jdkSerializer" />
</bean>
<redis:listener-container>
<redis:listener ref="smsMessageListener" method="handleMessage"
serializer="jdkSerializer" topic="sms_queue_web_online" />
</redis:listener-container>123456789
smsMessageListener:消息監聽器
redis:listener-container:定義消息監聽,method:監聽消息執行的方法,serializer:序列化,topic:監聽主題(可以理解為隊列名稱)
3.3代碼實現
1.定義簡訊消息對象SmsMessageVo
public class SmsMessageVo implements Serializable {
//id
private Integer smsId; //手機號
private String mobile; //類型,1:驗證碼 2:訂單通知
private Byte type; //簡訊創建時間
private Date createDate; //簡訊消息處理時間
private Date processTime; //簡訊狀態,1:未發送 2:發送成功 3:發送失敗
private Byte status; //簡訊內容
private String content; //省略setter和getter方法
...
2.定義消息隊列發送對象SendMessage
//SendMessage.javapublic class SendMessage { private RedisTemplate<String, Object> redisTemplate; public RedisTemplate<String, Object> getRedisTemplate() { return redisTemplate;
} public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate;
} public void sendMessage(String channel, Serializable message) {
redisTemplate.convertAndSend(channel, message);
}
}
3.發送消息
String smsContent = templateToContent(template.getContent(),
regMsgCode);
SmsMessageVo smsMessageVo = new SmsMessageVo();
smsMessageVo.setMobile(mobile);
smsMessageVo.setType((byte) SmsType.VERIFICATION.getType());
smsMessageVo.setChannelId(1);
smsMessageVo.setContent(smsContent);
smsMessageVo.setCreateDate(new Date());
smsMessageVo.setStatus((byte) SmsSendStatus.TO_SEND.getType());
smsMessageVo.setTemplateId(1);
//先把待發送的簡訊存入資料庫
SmsQueue smsQueue = new SmsQueue();
BeanUtils.Properties(smsQueue, smsMessageVo);
smsQueueService.addSmsQueue(smsQueue);
//非同步發送簡訊到redis隊列
sendMessage.sendMessage(Constants.REDIS_QUEUE_SMS_WEB, smsMessageVo);
//Constants.REDIS_QUEUE_SMS_WEB = "sms_queue_web_online",和applicationContext-redis中topic配置一樣
4.監聽消息
//SmsMessageDelegateListener.java@Component("smsMessageDelegateListener")public class SmsMessageDelegateListener {
@Autowired
private SmsQueueService smsQueueService; //監聽Redis消息
public void handleMessage(Serializable message){ if(message instanceof SmsMessageVo){
SmsMessageVo messageVo = (SmsMessageVo) message; //發送簡訊
SmsSender smsSender = SmsSenderFactory.buildEMaySender();
smsSender.setMobile(messageVo.getMobile());
smsSender.setContent(messageVo.getContent()); boolean sendSucc = false; //判斷簡訊類型
//驗證碼簡訊
if(messageVo.getType() == (byte)SmsType.VERIFICATION.getType()){
sendSucc = smsSender.send();
} if(!sendSucc){ return;
} // 非同步更新簡訊表狀態為發送成功
final Integer smsId = messageVo.getSmsId();
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Runnable() { public void run() {
SmsQueue smsQueue = new SmsQueue();
smsQueue.setSmsId(smsId);
smsQueue.setStatus((byte)SmsSendStatus.SEND.getType());
smsQueue.setProcessTime(new Date());
smsQueueService.updateSmsQueue(smsQueue);
}
});
}
}
}04142434445
4.總結
下面使用一張流程圖,來總結Redis消息隊列和簡訊服務。
閱讀全文
㈧ java連接redis超時問題怎麼解決
應該是redis本身的服務有問題了
本文所針對的連接超時問題所涉及的相關元素如下:
Redis客戶端: Jedis (java)
Redis版本 :2.8.12
Redis部署操作系統類型:Linux
正文開始:
No 1.Redis執行大命令(時間復雜度為O(N)的命令)
問題剖析:
a.Redis伺服器端通過單線程處理命令,一旦有大命令被執行,Redis將無法及時響應來自客戶端的任何命令
關於Redis大命令的監控,可以查看slowlog來觀察
b.在使用jedis作為redis客戶端時,當redis連接池的配置參數testOnBorrow=true時,默認會在獲取redis連接
時,先執行redis的ping方法,而基於原因a,此時redis將無法及時響應,自然會報出time out異常
如何解決:
a.盡量避免使用時間復雜度為O(N)的命令
b.如果無法避免使用時間復雜度為O(N)的命令,則應降低其使用頻率,避免在業務高峰期時使用
No 2.Redis單次操作數據包過大
問題分析
a.單次操作數據包過大,且操作頻繁,極有可能會導致網路擁堵
b.在使用jedis作為redis客戶端時,當redis連接池的配置參數testOnBorrow=true時,默認會在獲取redis連接
時,先執行redis的ping方法,而基於原因a,此時redis將無法及時響應,自然會報出time out異常
如何解決:
a.排查代碼,確定是否存在大數據(數據條目過多/單條數據過大)操作,將其進行改造,改造方案有兩個:
a1.數據拆分,變更數據類型(常見的情況是將java中的collection類型序列化後存入redis的String數據
類型中),如將String數據類型調整為hash/list/set等,這常用於解決單條數據量過大的情況
a2.調整業務邏輯,減少單次數據查詢范圍(常見的情況如將redis中的整個hash數據取回,在應用程序內存中獲取需要的entry),如使用hget等單條查詢命令替換hgetall命令
㈨ redis什麼時候插入數據需要做序列化
java把對象從內存放到硬碟為啥需要序列化?內存可能是用堆棧、寄存器存儲的,斷電後消失(RAM);但是磁碟不一樣,磁碟固化數據(ROM)。
需
要序列化,主要是一種針對需要I/O操作的,此時寫入磁碟恰巧需要I/O。讓類實現serializable介面,此類的對象就可以被序列化了。針對對象
的對象流:ObjectOutputStream,調用writeObject()/readObject()可以實現序列化、反序列化。