1. 如何在.Net中使用Redis
比較流行的也是官方推薦的 .Net 訪問 Redis 的中間件
ServiceStack
StackExchange
ServiceStack.Redis 4.* 的版本,開始有條件收費,好像是達到一定請求量就會收費
還好 4.* 以前的是免費的
StackExchange 是免費,但是,最近聽說要收費,待驗證
區別
收費和免費的區別。收費就會享受收費的服務,免費,人家就沒有那個義務
ServiceStack 存取數據,可以直接進行序列化和反序列化。StackExchang 需要自己處理序列化和反序列化
ServiceStack 提供了大量可用的程序集,可以提高很多方面的開發效率。StackExchange,規模相對小很多
使用方面,個人覺著 ServiceStack 使用上更方便一些,而且文檔也更豐富
源碼
在github上都是可以搜索到源碼,來學習參考的
2. Java工程師是如何使用Redis的
redis算是用的最多的key-value型緩存組件了!
因為使用了key-value型,所以存取效率極好,簡單來說就類似JAVA中的hashMap,不過是用整個伺服器內存來當做map,但是redis的數據可以通過配置指令保存到硬碟(同步保存save,非同步保存bgsave)!
當然,redis在使用過程中會存在持久化失敗,緩存擊穿,擴容困難等問題,不過無論如何,redis都是一款最值得用的緩存工具!
使用過程中有任何問題,歡迎大家一起交流,redis還有什麼遺漏功能,也請大家補充,謝謝!
3. 到底如何在spring中使用redis
1. Redis使用場景
Redis是一個開源的使用ANSI C語言編寫、支持網路、可基於內存亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。
我們都知道,在日常的應用中,資料庫瓶頸是最容易出現的。數據量太大和頻繁的查詢,由於磁碟IO性能的局限性,導致項目的性能越來越低。
這時候,基於內存的緩存框架,就能解決我們很多問題。例如Memcache,Redis等。將一些頻繁使用的數據放入緩存讀取,大大降低了資料庫的負擔。提升了系統的性能。
其實,對於hibernate的二級緩存,是同樣的道理。利用內存高速的讀寫速度,來解決硬碟的瓶頸。
2. 配置使用redis
首先,我們需要引入基本的jar包。maven中的基本引用如下:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.4.2.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.2</version>
</dependency>
然後,在applicationContext中配置如下:
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
p:pool-config-ref="poolConfig" />
<bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<!-- 開啟事務,可以通過transcational註解控制 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="keySerializer" ref="stringSerializer" />
<property name="enableTransactionSupport" value="true" />
</bean>
對於hibernate的配置可知,第一個poolconfig是對連接池的配置。包括最大連接數,隊列數,存活時間,最大等待時間等等,還有一些額外的配置,請直接點擊JedisPoolConfig類源碼,進行查看。
這些配置的意思如果不明白的話,一定要去把線程池好好學習下。
第一個配置是連接工廠,顧名思義,最基本的使用一定是對連接的打開和關閉。我們需要為其配置redis伺服器的賬戶密碼,埠號。(這里還可以配置資料庫的index,但是我使用時候一直使用redis的默認資料庫,也就是第0個)
最後一個配置特別重要。這個類似於spring提供的HibernateDaoSupport。
接下來,全部講解都將圍繞這個類展開。
3. RedisTemplate的使用
這個類作為一個模版類,提供了很多快速使用redis的api,而不需要自己來維護連接,事務。
最初的時候,我創建的BaseRedisDao是繼承自這個類的。繼承的好處是我的每個Dao中,都可以自由的控制序列化器,自由的控制自己是否需要事務,這個先不需要了解,跟著我目前的這種配置方法來即可。
template提供了一系列的operation,比如valueOperation,HashOperation,ListOperation,SetOperation等,用來操作不同數據類型的Redis。
並且,RedisTemplate還提供了對應的*OperationsEditor,用來通過RedisTemplate直接注入對應的Operation。我們暫時不講這個。
對於下面的test1方法,我們暫時不用考慮,先了解通過RedisTemplate來使用connection操作Redis。
Test代碼如下:
package cn.test.spjedis;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework..DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.cn.redis2..IncrDao;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestRedis {
@Resource(name = "redisTemplate")
private RedisTemplate<String, String> template; // inject the template as ListOperations
//至於這個為什麼可以注入。需要參考AbstractBeanFactory doGetBean
//super.setValue(((RedisOperations) value).opsForValue());就這一行代碼 依靠一個editor
@Resource(name = "redisTemplate")
private ValueOperations<String, Object> vOps;
public void testSet(){
template.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
byte [] key = "tempkey".getBytes();
byte[] value = "tempvalue".getBytes();
connection.set(key, value);
return true;
}
});
}
public void testSet1(){
vOps.set("tempkey", "tempvalue");
}
@Autowired
private IncrDao incr;
@Test
public void addLink() {
System.out.println(incr.incr(13));
System.out.println(incr.get(13));
}
}
這個是對String類型插入的兩個測試。test方法中,使用了模版類提交回調(RedisCallBack)的方法來使用jedis connection操作數據。這一部分,有沒有似曾相識呢?
HibernateTemplate的HibernateCallback,以及Hibernate Session類中的doWork以及doReturningWork方法,都是使用了這樣的機制,方便對於連接或者session的統一管理。
public int excuteHqlUpdate(final String hql,final Object ...params){
return getHibernateTemplate().executeWithNativeSession(new HibernateCallback<Integer>() {
@Override
@SuppressWarnings("unchecked")
public Integer doInHibernate(Session session) throws HibernateException {
Query queryObject = session.createQuery(hql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
queryObject.setParameter(i, params[i]);
}
}
return queryObject.executeUpdate();
}
});
}
4. php redis如何使用
開始在 PHP 中使用 Redis 前,要確保已經安裝了 redis 服務及 PHP redis 驅動,且你的機器上能正常使用 PHP。
PHP安裝redis擴展
/usr/local/php/bin/phpize #php安裝後的路徑
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
修改php.ini文件
vi /usr/local/php/lib/php.ini
增加如下內容:
extension_dir = "/usr/local/php/lib/php/extensions/no-debug-zts-20090626"
extension=redis.so
安裝完成後重啟php-fpm 或 apache。查看phpinfo信息,就能看到redis擴展。
連接到 redis 服務
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
//查看服務是否運行
echo "Server is running: " . $redis->ping();
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Server is running: PONG
Redis PHP String(字元串) 實例
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
//設置 redis 字元串數據
$redis->set("tutorial-name", "Redis tutorial");
// 獲取存儲的數據並輸出
echo "Stored string in redis:: " . jedis.get("tutorial-name");
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Stored string in redis:: Redis tutorial
Redis PHP List(列表) 實例
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
//存儲數據到列表中
$redis->lpush("tutorial-list", "Redis");
$redis->lpush("tutorial-list", "Mongodb");
$redis->lpush("tutorial-list", "Mysql");
// 獲取存儲的數據並輸出
$arList = $redis->lrange("tutorial-list", 0 ,5);
echo "Stored string in redis:: "
print_r($arList);
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Stored string in redis::
Redis
Mongodb
Mysql
Redis PHP Keys 實例
<?php
//連接本地的 Redis 服務
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
echo "Connection to server sucessfully";
// 獲取數據並輸出
$arList = $redis->keys("*");
echo "Stored keys in redis:: "
print_r($arList);
?>
執行腳本,輸出結果為:
Connection to server sucessfully
Stored string in redis::
tutorial-name
tutorial-list
5. 如何在.Net中使用Redis
Redis安裝與啟動1.下載RedisRedis本身沒有提供Windows版本的,並且在Windows上也不太穩定,一般都將其部署到Linux環境下,Redis可以在其官網上下載,MSOpenTech中提供了Windows版本,這里為了學習安裝這一版本。點擊跳轉到Github後,直接點擊Zip下載。下載後根據自己計算機的版本選擇32位或者64位進行安裝。我將64位的解壓後放到D:\Redis文件夾下,同時將文件夾內的redis.conf也拷貝到該目錄下,這個是redis的配置信息:2.啟動Redis在Windows下面啟用Redis和啟動MogoDB一樣,需要使用命令行啟動,首先定位到該目錄,運行如下命令:D:\Redis>redis-server.exeredis.conf因為是在本機運行的,這里要注意埠號,同時要保持埠不要關閉。當然您也可以將Redis作為Windows服務在後台一直開啟。3.使用現在再開一個控制台應用程序連接之前啟動的Redis,如下:D:\Redis>redis-cli.exe-h172.16.147.121-p6379其中–h後面是本機的ip地址,後面的是埠。然後就可以執行set給key為city賦值:redis172.16.147.121:6379>setcityShanghai通過get可以獲取指定key為city的值了。redis172.16.147.121:6379>getcity同時,在我們往redis上寫數據的時候,Redis服務也會定時的往文件中寫數據這里僅簡單的介紹了get和set命令,命令可以查看mands.初探Redis下載ServiceStack.Redis和MongoDB一樣,在.NET中使用Redis其實也是使用第三方驅動,官網推薦的是使用ServiceStack.Redis下載後解壓得到如下dll.NET項目中使用Redis新建一個Console程序,引用上一步驟解壓的四個dll。做一個簡單的例子,在.NET中獲取之前我們設置的city的值。classProgram{staticRedisClientredisClient=newRedisClient("172.16.147.121",6379);//redis服務IP和埠staticvoidMain(string[]args){Console.WriteLine(redisClient.Get("city"));Console.ReadKey();}}首先通過staticRedisClientredisClient=newRedisClient("172.16.147.121",6379);建立連接,然後就可以直接用redisClient裡面的Get方法獲取key為city的值了。在前面的命令行中,我們網city中存入了Shanghai,現在我們獲取到了這個值。ServerStack中有很多方法可以在.NET中調用,其類結構圖如下:總結本文簡單介紹了Redis,Redis如何在Windows下安裝,以及如何在.NET中使用訪問和使用Redis,希望對您有所幫助,下文將講解如何在.NET中網Redis中讀寫復雜對象。
6. 如何使用Redis
Redis是基於key-value範式存儲數據,所以先來重點看下"key"的概念。
key本質上就是簡單的字元串,諸如"username"、"password"等。在定義key時,除了不能使用空格,你可以隨意的使用普通的字元、數字等,像".",":","_"等在定義key時都能正常使用,所以像"user_name", "user:123:age", "user:123:username"都是不錯的key的定義方式。
不像RDBMS中的欄位名稱,這里的key是Redis中的重要組成部分,所以我們必須在處理key時多加小心。在下面的講述中,Redis並沒有table的概念,所以像"SELECT username from users WHERE user_id=123;"這種簡單任務都只能換種方式實現,為了達到這種目的,在Redis上,一種方式是通過key "user:123:username"來獲取結果value。如你所見,key的定義中攜帶了神秘信息(像user ids)。在Redis中,key的重要性可見一斑。(其他key-value資料庫中key的地位也是如此。)
7. 如何在 Go 語言中使用 Redis 連接池
在創建連接池之後,起一個 goroutine,每隔一段 idleTime 發送一個 PING 到 Redis server。其中,idleTime 略小於 Redis server 的 timeout 配置。
連接池初始化部分代碼如下:
p, err := pool.New("tcp", u.Host, concurrency)
errHndlr(err)
go func() {
for {
p.Cmd("PING")
time.Sleep(idelTime * time.Second)
}
}()
使用 redis 傳輸數據部分代碼如下:
func redisDo(p *pool.Pool, cmd string, args ...interface{}) (reply *redis.Resp, err error) {
reply = p.Cmd(cmd, args...)
if err = reply.Err; err != nil {
if err != io.EOF {
Fatal.Println("redis", cmd, args, "err is", err)
}
}
return
}
其中,Radix.v2 連接池內部進行了連接池內連接的獲取和放回,代碼如下:
// Cmd automatically gets one client from the pool, executes the given command
// (returning its result), and puts the client back in the pool
func (p *Pool) Cmd(cmd string, args ...interface{}) *redis.Resp {
c, err := p.Get()
if err != nil {
return redis.NewResp(err)
}
defer p.Put(c)
return c.Cmd(cmd, args...)
}
這樣,我們就有了 keepalive 的機制,不會出現 timeout 的連接了,從 redis 連接池裡面取出的連接都是可用的連接了。
8. 如何使用Redis
應用Redis實現數據的讀寫,同時利用隊列處理器定時將數據寫入mysql。 同時要注意避免沖突,在redis啟動時去mysql讀取所有表鍵值存入redis中,往redis寫數據時,對redis主鍵自增並進行讀取,若mysql更新失敗,則需要及時清除緩存及同步redis主鍵...
9. java 中redis 如何使用
這是我之前寫的代代碼,可以參考一下:
importjava.util.Set;
importcom.google.gson.Gson;
importredis.clients.jedis.Jedis;
importredis.clients.jedis.JedisPool;
importredis.clients.jedis.JedisPoolConfig;
publicclassApp{
publicstaticvoidmain(String[]args){
JedisPoolConfigconfig=newJedisPoolConfig();
config.setMaxIdle(5);
config.setMaxWaitMillis(10000);
config.setTestOnBorrow(false);
JedisPooljedisPool=newJedisPool(config,"127.0.0.1",6379);
Jedisjedis=jedisPool.getResource();
jedis.flushDB();
jedis.set("name","Tom");
Useruser=newUser(1,"Tom","User");
Gsongson=newGson();
Stringjson=gson.toJson(user);
jedis.set("user1",json);
Set<String>keys=jedis.keys("*");
for(Stringkey:keys){
System.out.println(key);
}
}
}
如果有疑問,可以隨時追問。
10. 如何在 Go 語言中使用 Redis 連接池
一、關於連接池
一個資料庫伺服器只擁有有限的資源,並且如果你沒有充分使用這些資源,你可以通過使用更多的連接來提高吞吐量。一旦所有的資源都在使用,那麼你就不 能通過增加更多的連接來提高吞吐量。事實上,吞吐量在連接負載較大時就開始下降了。通常可以通過限制與可用的資源相匹配的資料庫連接的數量來提高延遲和吞 吐量。
如何在Go語言中使用Redis連接池
如果不使用連接池,那麼,每次傳輸數據,我們都需要進行創建連接,收發數據,關閉連接。在並發量不高的場景,基本上不會有什麼問題,一旦並發量上去了,那麼,一般就會遇到下面幾個常見問題:
性能普遍上不去
CPU 大量資源被系統消耗
網路一旦抖動,會有大量 TIME_WAIT 產生,不得不定期重啟服務或定期重啟機器
伺服器工作不穩定,QPS 忽高忽低
要想解決這些問題,我們就要用到連接池了。連接池的思路很簡單,在初始化時,創建一定數量的連接,先把所有長連接存起來,然後,誰需要使用,從這里取走,幹完活立馬放回來。 如果請求數超出連接池容量,那麼就排隊等待、退化成短連接或者直接丟棄掉。
二、使用連接池遇到的坑
最近在一個項目中,需要實現一個簡單的 Web Server 提供 Redis 的 HTTP interface,提供 JSON 形式的返回結果。考慮用 Go 來實現。
首先,去看一下 Redis 官方推薦的 Go Redis driver。官方 Star 的項目有兩個:Radix.v2 和 Redigo。經過簡單的比較後,選擇了更加輕量級和實現更加優雅的 Radix.v2。
Radix.v2 包是根據功能劃分成一個個的 sub package,每一個 sub package 在一個獨立的子目錄中,結構非常清晰。我的項目中會用到的 sub package 有 redis 和 pool。
由於我想讓這種被 fork 的進程最好簡單點,做的事情單一一些,所以,在沒有深入去看 Radix.v2 的 pool 的實現之前,我選擇了自己實現一個 Redis pool。(這里,就不貼代碼了。後來發現自己實現的 Redis pool 與 Radix.v2 實現的 Redis pool 的原理是一樣的,都是基於 channel 實現的, 遇到的問題也是一樣的。)
不過在測試過程中,發現了一個詭異的問題。在請求過程中經常會報 EOF 錯誤。而且是概率性出現,一會有問題,一會又好了。通過反復的測試,發現 bug 是有規律的,當程序空閑一會後,再進行連續請求,會發生3次失敗,然後之後的請求都能成功,而我的連接池大小設置的是3。再進一步分析,程序空閑300秒 後,再請求就會失敗,發現我的 Redis server 配置了 timeout 300,至此,問題就清楚了。是連接超時 Redis server 主動斷開了連接。客戶端這邊從一個超時的連接請求就會得到 EOF 錯誤。
然後我看了一下 Radix.v2 的 pool 包的源碼,發現這個庫本身並沒有檢測壞的連接,並替換為新server{location/pool{content_by_lua_block{localredis=require"resty.redis"localred=redis:new()localok,err=red:connect("127.0.0.1",6379)ifnotokthenngx.say("failedtoconnect:",err)returnendok,err=red:set("hello","world")ifnotokthenreturnendred:set_keepalive(10000,100)}}}
發現有個 set_keepalive 的方法,查了一下官方文檔,方法的原型是 syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size) 貌似 max_idle_timeout 這個參數,就是我們所缺少的東西,然後進一步跟蹤源碼,看看裡面是怎麼保證連接有效的。
function_M.set_keepalive(self,...)localsock=self.sockifnotsockthenreturnnil,"notinitialized"endifself.subscribedthenreturnnil,"subscribedstate"endreturnsock:setkeepalive(...)end
至此,已經清楚了,使用了 tcp 的 keepalive 心跳機制。
於是,通過與 Radix.v2 的作者一些討論,選擇自己在 redis 這層使用心跳機制,來解決這個問題。
四、最後的解決方案
在創建連接池之後,起一個 goroutine,每隔一段 idleTime 發送一個 PING 到 Redis server。其中,idleTime 略小於 Redis server 的 timeout 配置。連接池初始化部分代碼如下:
p,err:=pool.New("tcp",u.Host,concurrency)errHndlr(err)gofunc(){for{p.Cmd("PING")time.Sleep(idelTime*time.Second)}}()
使用 redis 傳輸數據部分代碼如下:
funcredisDo(p*pool.Pool,cmdstring,args...interface{})(reply*redis.Resp,errerror){reply=p.Cmd(cmd,args...)iferr=reply.Err;err!=nil{iferr!=io.EOF{Fatal.Println("redis",cmd,args,"erris",err)}}return}
其中,Radix.v2 連接池內部進行了連接池內連接的獲取和放回,代碼如下:
//,executesthegivencommand//(returningitsresult),(p*Pool)Cmd(cmdstring,args...interface{})*redis.Resp{c,err:=p.Get()iferr!=nil{returnredis.NewResp(err)}deferp.Put(c)returnc.Cmd(cmd,args...)}
這樣,我們就有了 keepalive 的機制,不會出現 timeout 的連接了,從 redis 連接池裡面取出的連接都是可用的連接了。看似簡單的代碼,卻完美的解決了連接池裡面超時連接的問題。同時,就算 Redis server 重啟等情況,也能保證連接自動重連。