亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MySQL > 正文

Mysql全局ID生成方法

2024-07-24 13:08:21
字體:
來源:轉載
供稿:網友
本文給大家介紹mysql全局id生成方法,涉及到mysql全局id相關知識,感興趣的朋友一起學習吧
 

生產系統隨著業務增長總會經歷一個業務量由小變大的過程,可擴展性是考量數據庫系統高可用性的一個重要指標;在單表/數據庫數據量過大,更新量不斷飆漲時,MySQL DBA往往會對業務系統提出sharding的方案。既然要sharding,那么不可避免的要討論到sharding key問題,在有些業務系統中,必須保證sharding key全局唯一,比如存放商品的數據庫等,那么如何生成全局唯一的ID呢,下文將從DBA的角度介紹幾種常見的方案。

1、使用CAS思想

什么是CAS協議

Memcached于1.2.4版本新增CAS(Check and Set)協議類同于Java并發的CAS(Compare and Swap)原子操作,處理同一item被多個線程更改過程的并發問題

CAS的基本原理

基本原理非常簡單,一言以蔽之,就是“版本號”,每個存儲的數據對象,都有一個版本號。

我們可以從下面的例子來理解:

不采用CAS,則有如下的情景:

 •第一步,A取出數據對象X;
 •第二步,B取出數據對象X;
 •第三步,B修改數據對象X,并將其放入緩存;
 •第四步,A修改數據對象X,并將其放入緩存。

結論:第四步中會產生數據寫入沖突。

采用CAS協議,則是如下的情景。

 •第一步,A取出數據對象X,并獲取到CAS-ID1;

•第二步,B取出數據對象X,并獲取到CAS-ID2; 

•第三步,B修改數據對象X,在寫入緩存前,檢查CAS-ID與緩存空間中該數據的CAS-ID是否一致。結果是“一致”,就將修改后的帶有CAS-ID2的X寫入到緩存。

 •第四步,A修改數據對象Y,在寫入緩存前,檢查CAS-ID與緩存空間中該數據的CAS-ID是否一致。結果是“不一致”,則拒絕寫入,返回存儲失敗。

這樣CAS協議就用了“版本號”的思想,解決了沖突問題。(樂觀鎖概念)

其實這里并不是嚴格的CAS,而是使用了比較交換原子操作的思想。

生成思路如下:每次生成全局id時,先從sequence表中獲取當前的全局最大id。然后在獲取的全局id上做加1操作,加1后的值更新到數據庫,如加1后的值為203,表名是users,數據表結構如下:

CREATE TABLE `SEQUENCE` (  `name` varchar(30) NOT NULL COMMENT '分表的表名',  `gid` bigint(20) NOT NULL COMMENT '最大全局id',  PRIMARY KEY (`name`)) ENGINE=innodb 

sql語句

update sequence set gid = 203 where name = 'users' and gid < 203; 

sql語句的 and gid < 203 是為了保證并發環境下gid的值只增不減。

如果update語句的影響記錄條數為0說明,已經有其他進程提前生成了203這個值,并寫入了數據庫。需要重復以上步驟從新生成。

代碼實現如下:

//$name 表名function next_id_db($name){  //獲取數據庫全局sequence對象  $seq_dao = Wk_Sequence_Dao_Sequence::getInstance();  $threshold = 100; //最大嘗試次數  for($i = 0; $i < $threshold; $i++){    $last_id = $seq_dao->get_seq_id($name);//從數據庫獲取全局id    $id = $last_id +1;    $ret = $seq_dao->set_seq_id($name, $id);    if($ret){      return $id;      break;    }  }  return false;}

2、使用全局鎖

在進行并發編程時,一般都會使用鎖機制。其實,全局id的生成也是解決并發問題。

生成思路如下:

在使用redis的setnx方法和memcace的add方法時,如果指定的key已經存在,則返回false。利用這個特性,實現全局鎖

每次生成全局id前,先檢測指定的key是否存在,如果不存在則使用redis的incr方法或者memcache的increment進行加1操作。這兩個方法的返回值是加1后的值,如果存在,則程序進入循環等待狀態。循環過程中不斷檢測key是否還存在,如果key不存在就執行上面的操作。

代碼如下:

//使用redis實現//$name 為 邏輯表名function next_id_redis($name){  $redis = Wk_Redis_Util::getRedis();//獲取redis對象  $seq_dao = Wk_Sequence_Dao_Sequence::getInstance();//獲取存儲全局id數據表對象  if(!is_object($redis)){    throw new Exception("fail to create redis object");  }  $max_times = 10; //最大執行次數 避免redis不可用的時候 進入死循環  while(1){    $i++;    //檢測key是否存在,相當于檢測鎖是否存在    $ret = $redis->setnx("sequence_{$name}_flag",time());    if($ret){      break;    }    if($i > $max_times){      break;    }    $time = $redis->get("sequence_{$name}_flag");    if(is_numeric($time) && time() - $time > 1){//如果循環等待時間大于1秒,則不再等待。      break;    }  }  $id = $redis->incr("sequence_{$name}");  //如果操作失敗,則從sequence表中獲取全局id并加載到redis  if (intval($id) === 1 or $id === false) {    $last_id = $seq_dao->get_seq_id($name);//從數據庫獲取全局id    if(!is_numeric($last_id)){      throw new Exception("fail to get id from db");    }    $ret = $redis->set("sequence_{$name}",$last_id);    if($ret == false){      throw new Exception("fail to set redis key [ sequence_{$name} ]");    }    $id = $redis->incr("sequence_{$name}");    if(!is_numeric($id)){      throw new Exception("fail to incr redis key [ sequence_{$name} ]");    }  }  $seq_dao->set_seq_id($name, $id);//把生成的全局id寫入數據表sequence  $redis->delete("sequence_{$name}_flag");//刪除key,相當于釋放鎖  $db = null;  return $id;} 

3、redis和db結合

使用redis直接操作內存,可能性能會好些。但是如果redis死掉后,如何處理呢?把以上兩種方案結合,提供更好的穩定性。
代碼如下:

function next_id($name){  try{    return $this->next_id_redis($name);  }  catch(Exception $e){    return $this->next_id_db($name);  }} 

4、Flicker的解決方案

因為mysql本身支持auto_increment操作,很自然地,我們會想到借助這個特性來實現這個功能。Flicker在解決全局ID生成方案里就采用了MySQL自增長ID的機制(auto_increment + replace into + MyISAM)。一個生成64位ID方案具體就是這樣的:
先創建單獨的數據庫(eg:ticket),然后創建一個表:

CREATE TABLE Tickets64 (      id bigint(20) unsigned NOT NULL auto_increment,      stub char(1) NOT NULL default '',      PRIMARY KEY (id),      UNIQUE KEY stub (stub)  ) ENGINE=MyISAM 

當我們插入記錄后,執行SELECT * from Tickets64,查詢結果就是這樣的:

+-------------------+------+
| id                | stub |
+-------------------+------+
| 72157623227190423 |    a |
+-------------------+------+

在我們的應用端需要做下面這兩個操作,在一個事務會話里提交:

REPLACE INTO Tickets64 (stub) VALUES ('a');SELECT LAST_INSERT_ID(); 

這樣我們就能拿到不斷增長且不重復的ID了。
到上面為止,我們只是在單臺數據庫上生成ID,從高可用角度考慮,
接下來就要解決單點故障問題:Flicker啟用了兩臺數據庫服務器來生成ID,
通過區分auto_increment的起始值和步長來生成奇偶數的ID。

TicketServer1:auto-increment-increment = 2auto-increment-offset = 1TicketServer2:auto-increment-increment = 2auto-increment-offset = 2 

最后,在客戶端只需要通過輪詢方式取ID就可以了。

 •優點:充分借助數據庫的自增ID機制,提供高可靠性,生成的ID有序。

 •缺點:占用兩個獨立的MySQL實例,有些浪費資源,成本較高。

以上內容是小編給大家分享的Mysql全局ID生成方法,希望大家喜歡。



注:相關教程知識閱讀請移步到MYSQL教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人三级视频网站| 91精品啪在线观看麻豆免费| 亚洲成人久久久| 高清亚洲成在人网站天堂| 日韩欧美在线一区| 国产69精品久久久久9999| 久久影院模特热| 成人乱色短篇合集| 国内精品久久影院| 午夜精品一区二区三区视频免费看| 国产精品第三页| 亚洲人成在线播放| 91精品国产色综合| 国产91免费看片| 国产精品久久久久久久久久久久久久| 国产精品视频网| 日韩欧美a级成人黄色| 91嫩草在线视频| 亚洲欧美制服第一页| 亚洲国产精品久久精品怡红院| 中文字幕一区二区精品| 色综合老司机第九色激情| 国产在线视频一区| 91手机视频在线观看| 91av成人在线| 久久精品中文字幕免费mv| 色与欲影视天天看综合网| 亚洲日本成人女熟在线观看| 久久精品99国产精品酒店日本| 亚洲伊人久久综合| 黄色成人av网| 中日韩午夜理伦电影免费| 欧美一区二区三区精品电影| 久久久国产精品视频| 中文字幕自拍vr一区二区三区| 国产精品欧美日韩| 欧美精品videosex牲欧美| 亚洲最大福利视频| 欧美与黑人午夜性猛交久久久| 国产日韩综合一区二区性色av| 一区二区三区无码高清视频| 热久久视久久精品18亚洲精品| 亚洲美腿欧美激情另类| 欧美性xxxx| 欧美激情一级精品国产| 不卡伊人av在线播放| 欧美日韩国产在线看| 亚洲成年网站在线观看| 亚洲美女又黄又爽在线观看| 成人午夜在线视频一区| 日韩精品一二三四区| 91久久久久久久| 一区二区三区高清国产| 久久成人免费视频| 欧美高清理论片| 一个人看的www欧美| 国产精品丝袜久久久久久不卡| 欧美黄色片视频| 国产精品91久久久久久| 欧美性猛交99久久久久99按摩| 久久久久久91| 久久精品国产一区二区电影| 懂色av中文一区二区三区天美| 色婷婷综合久久久久中文字幕1| 亚洲欧美日韩天堂一区二区| 亚洲色图偷窥自拍| 在线视频欧美日韩精品| 欧美怡春院一区二区三区| 黑人精品xxx一区| 欧美另类极品videosbest最新版本| 欧美孕妇孕交黑巨大网站| 国产精品久久久久久久app| 欧美激情按摩在线| 日韩精品欧美激情| 欧美激情极品视频| 成人国产精品av| 日韩欧美一区二区三区久久| 欧美精品电影免费在线观看| 日韩精品极品视频免费观看| 欧美国产日韩中文字幕在线| 91日韩在线视频| 日韩av一区二区在线观看| 国内精品美女av在线播放| 国产一区二区在线免费| 1769国产精品| 欧美裸身视频免费观看| 夜夜狂射影院欧美极品| 国产精品久久久久久av下载红粉| 久久久久久久久久久久av| 亚洲福利在线观看| 亚洲高清福利视频| 欧美激情久久久久久| 国产精品a久久久久久| 欧美日韩国产精品| 狠狠躁夜夜躁人人爽天天天天97| 亚洲国产精彩中文乱码av| 欧美日本在线视频中文字字幕| 亚洲人成伊人成综合网久久久| 久久成人精品电影| 欧美成人精品在线| 精品国产乱码久久久久久婷婷| 亚洲人精选亚洲人成在线| 亚洲一区二区黄| 97精品免费视频| 国产精品视频网站| 亚洲美腿欧美激情另类| 91亚洲精品久久久久久久久久久久| 亚洲第一精品电影| 人妖精品videosex性欧美| 久久伊人精品天天| www.国产精品一二区| 欧美视频在线免费| 成人网页在线免费观看| 热99精品里视频精品| 亚洲天堂网在线观看| 国产精品日韩在线| 91在线色戒在线| 欧美老少配视频| 欧美在线播放视频| 国产成人a亚洲精品| 国产美女精彩久久| 激情亚洲一区二区三区四区| 自拍亚洲一区欧美另类| 亚洲国产精品yw在线观看| 2024亚洲男人天堂| 5566日本婷婷色中文字幕97| 国产亚洲成精品久久| 日韩av电影手机在线| 少妇精69xxtheporn| 亚洲有声小说3d| 91精品国产91久久| 国产美女高潮久久白浆| 91极品视频在线| 91精品久久久久久久久不口人| 中文字幕亚洲第一| 亚洲精品v欧美精品v日韩精品| 91久久精品国产| 亚洲午夜精品久久久久久性色| 亚洲欧洲日产国产网站| 伊人青青综合网站| 九九视频这里只有精品| 97久久超碰福利国产精品…| 国产日本欧美一区二区三区在线| 最新69国产成人精品视频免费| 成人国内精品久久久久一区| 日韩欧美高清在线视频| 一区二区三区四区精品| 欧美日韩国产色| 88国产精品欧美一区二区三区| 欧美黄网免费在线观看| 精品国产欧美成人夜夜嗨| 国产精品久久久久久久久久尿| 亚洲成人久久久| yw.139尤物在线精品视频| 亚洲免费视频观看| 成人看片人aa| 国产精品∨欧美精品v日韩精品| 在线视频中文亚洲| 91免费电影网站| 日韩精品视频免费| 精品国产自在精品国产浪潮| 亚洲精品久久久久久久久久久久久| 亚洲美女av在线| 国内揄拍国内精品|