- 暴露接口,按鈕防重複(點擊一次按鈕後就變成禁用,禁止重複提交)
- 採用CDN存儲靜態化的頁面和一些靜態資源(css,js等)
- Redis 是徹底開源免費的,遵照BSD協議,是一個高性能的key-value數據庫。
- Redis支持數據的持久化,能夠將內存中的數據保存在磁盤中,重啓的時候能夠再次加載進行使用。
- 性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
- 原子 – Redis的全部操做都是原子性的,意思就是要麼成功執行要麼失敗徹底不執行。
- 利用Redis能夠減輕MySQL服務器的壓力,減小了跟數據庫服務器的通訊次數。
詳細步驟參考:Redis服務端安裝教程css
注:如下pom.xml爲Maven項目配置文件,若非Maven項目,百度相應名稱包導入便可。html
<!-- redis客戶端:Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.3</version>
</dependency>
因爲Jedis並無實現內部序列化操做,而Java內置的序列化機制性能又不高,咱們須要考慮高併發優化,在這裏咱們採用開源社區提供的更高性能的自定義序列化工具protostuff。前端
<!-- protostuff序列化依賴 -->
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.0.8</version>
</dependency>
- 流程:先去Redis緩存中查詢,以此下降數據庫的壓力。若是在緩存中查詢不到數據再去數據庫中查詢,再將查詢到的數據放入Redis緩存中,這樣下次就能夠直接去緩存中直接查詢到。
- 推薦:新建dao.cache包,實現RedisDao類。例子中緩存實體類名爲Seckill.class。例子:
- 使用protostuff序列化工具時,被序列化的對象必須是pojo對象(具有setter/getter)
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/* * Redis能夠近似理解爲Map<Key,Value>對象 */
public class RedisDao {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final JedisPool jedisPool;
public RedisDao(String ip, int port) {
jedisPool = new JedisPool(ip, port);
}
private RuntimeSchema<Seckill> schema = RuntimeSchema.createFrom(Seckill.class);
public Seckill getSeckill(long seckillId) {
// redis操做邏輯
try {
Jedis jedis = jedisPool.getResource();
try {
String key = "seckill:" + seckillId;
// 並無實現內部序列化操做
// get-> byte[] -> 反序列化 ->Object(Seckill)
// 採用自定義序列化
// protostuff : pojo.
byte[] bytes = jedis.get(key.getBytes());//根據Key獲取Value
// 緩存中獲取到bytes
if (bytes != null) {
// 空對象
Seckill seckill = schema.newMessage();
ProtostuffIOUtil.mergeFrom(bytes, seckill, schema);
// seckill 被反序列化
return seckill;
}
} finally {
jedis.close();
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
public String putSeckill(Seckill seckill) {
// set Object(Seckill) -> 序列化 -> byte[]
try {
Jedis jedis = jedisPool.getResource();
try {
String key = "seckill:" + seckill.getSeckillId();//保存Value的Key
byte[] bytes = ProtostuffIOUtil.toByteArray(seckill, schema,
LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
// 超時緩存
int timeout = 60 * 60;// 1小時
String result = jedis.setex(key.getBytes(), timeout, bytes);
return result;
} finally {
jedis.close();
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
}
- 在使用該RedisDao對象時,須要傳入Ip地址和端口。
new RedisDao("localhost","6379");
- 若使用Spring ICO容器,需配置:
<!--redisDao -->
<bean id="redisDao" class="換成你的包dao.cache.RedisDao">
<constructor-arg index="0" value="localhost" />
<constructor-arg index="1" value="6379" />
</bean>
Seckill seckill = redisDao.getSeckill(id);
if (seckill == null) {
seckill = seckillDao.queryById(id);
if (seckill != null) {
String result = redisDao.putSeckill(seckill);
System.out.pritln(result);
seckill = redisDao.getSeckill(id);
System.out.pritln(result);
}
}