Redis多數據庫、事務、加鎖

一.多數據庫

一個redis實例能夠包含多個數據庫,客戶端能夠指定鏈接redis實例的哪一個數據庫。就比如咱們在mysql中能夠建立多個數據庫同樣,客戶端能夠指定鏈接哪一個數據庫。一個redis實例最多能夠提供16個數據庫,下標分別是從0-15,客戶端默認鏈接第0號數據庫。客戶端能夠經過select命令來選擇鏈接哪一個數據庫:java

select 1
#選擇鏈接1號數據庫

客戶端能夠經過move命令來將一個數據庫中的key移動到另外一個數據庫中mysql

select 0
move myset 1
#將0號數據庫中的myset移動到1號數據庫中

 

二.redis事務

在redis中可使用multi exec discard 這三個命令來實現事務。在事務中,全部命令會被串行化順序執行,事務執行期間redis不會爲其餘客戶端提供任何服務,從而保證事務中的命令都被原子化執行redis

  • multi      開啓事務,這後邊執行的命令都會被存到命令的隊列當中
  • exec      至關於關係型數據庫事務中的commit,提交事務
  • discard      至關於關係型數據庫事務中的rollback,回滾操做

示例:sql

三.加鎖

這裏用一個信用卡刷卡的例子來說redis加鎖的問題:數據庫

假設balance爲可用餘額,debt爲欠款,amtToSubtract爲實刷額度,刷卡操做涉及到balance(可用餘額)的減小和debt的增長,所以這裏用事務進行管理,多線程

package jedis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

public class TestTransaction {
	 
	  public boolean transMethod() throws InterruptedException {
	     Jedis jedis = new Jedis("10.2.1.121", 6379);
	     jedis.auth("123456");
	     int balance;// 可用餘額
	     int debt;// 欠額
	     int amtToSubtract = 10;// 實刷額度
	 
	     jedis.watch("balance");//標記balabce餘額
	     
	     balance = Integer.parseInt(jedis.get("balance"));
	     if (balance < amtToSubtract) {
	       jedis.unwatch();
	       System.out.println("modify");
	       return false;
	     } else {
	       System.out.println("***********transaction");
	       Transaction transaction = jedis.multi();//開啓事務

	       System.out.println("線程進入休眠......");
	       Thread.sleep(7000);
               //jedis.set("balance","5");//此處不應出現,這是模擬多線程下其餘程序已經修改了該條目,
                                          //測試時我是在線程休眠時,手動在redis客戶端中更改了balance的值

	       transaction.decrBy("balance", amtToSubtract);
	       transaction.incrBy("debt", amtToSubtract);
	       transaction.exec();//提交事務
	       balance = Integer.parseInt(jedis.get("balance"));
	       debt = Integer.parseInt(jedis.get("debt"));
	 
	       System.out.println("*******" + balance);
	       System.out.println("*******" + debt);
	       return true;
	     }
	  }
	 
	  
	  public static void main(String[] args) throws InterruptedException {
	     TestTransaction test = new TestTransaction();
	     boolean retValue = test.transMethod();
	     System.out.println("main retValue-------: " + retValue);
	  }
	}

通俗點講,watch命令就是標記一個鍵,若是標記了一個鍵, 在提交事務前若是該鍵被別人修改過,那事務就會失敗,這種狀況一般能夠在程序中從新再嘗試一次。
在本例中,就首先標記了鍵balance,而後檢查餘額是否足夠,不足就取消標記,並不作扣減; 足夠的話,就啓動事務進行更新操做,若是在此期間鍵balance被其它人修改, 那在提交事務(執行exec)時就會報錯, 程序中一般能夠捕獲這類錯誤再從新執行一次,直到成功。測試

相關文章
相關標籤/搜索