中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

找個人做網站還是找企業(yè)做網站自己如何優(yōu)化網站排名

找個人做網站還是找企業(yè)做網站,自己如何優(yōu)化網站排名,怎樣建企業(yè)網站,鄂爾多斯市建設廳網站數據庫分表有很多策略,如下: 數據庫分表是處理大型數據庫中數據量過大的一種常見策略,它可以提高查詢性能、減少鎖競爭、降低維護成本等。以下是一些常見的數據庫分表方案: 1. **垂直分表(Vertical Partitioning&…

數據庫分表有很多策略,如下:

數據庫分表是處理大型數據庫中數據量過大的一種常見策略,它可以提高查詢性能、減少鎖競爭、降低維護成本等。以下是一些常見的數據庫分表方案:

1. **垂直分表(Vertical Partitioning)**:
? ?- 將表中的一部分列拆分到新的表中,通常是根據列的使用頻率或者數據類型。
? ?- 適用于查詢中只涉及部分列的情況。

2. **水平分表(Horizontal Partitioning)**:
? ?- 將表中的行拆分到多個表中,每個表結構相同,但數據行不同。
? ?- 可以基于某個鍵值(如用戶ID、日期等)進行分片。

3. **基于范圍的分表**:
? ?- 按照數據的某個屬性值的范圍進行分表,例如按照時間范圍(每月一個表)。

4. **基于列表的分表**:
? ?- 根據某個離散的屬性值進行分表,例如用戶ID或地區(qū)ID。

5. **復合分表**:
? ?- 結合垂直分表和水平分表,先按列分表,再按行分表。

6. **哈希分表**:
? ?- 使用哈希函數根據某個鍵值將數據均勻分配到多個表中。

7. **列表分表**:
? ?- 根據數據的某個屬性值(如枚舉類型)將數據分配到不同的表中。

8. **一致性哈希分表**:
? ?- 適用于分布式系統(tǒng)中,通過一致性哈希算法將數據分配到不同的節(jié)點或表中。

9. **分區(qū)分表**:
? ?- 在數據庫中創(chuàng)建不同的分區(qū),每個分區(qū)可以獨立查詢。

10. **按業(yè)務邏輯分表**:
? ? - 根據業(yè)務模塊或邏輯將數據分配到不同的表中。

實施分表策略時,需要考慮以下因素:

- **查詢模式**:分析應用的查詢模式,確保分表策略能夠優(yōu)化這些查詢。
- **數據訪問頻率**:經常訪問的數據應該放在容易訪問的位置。
- **數據增長**:預測數據增長趨勢,確保分表策略能夠適應未來的數據量。
- **維護成本**:分表會增加維護的復雜性,需要權衡性能提升和維護成本。
- **事務一致性**:分表可能會影響事務的處理,需要確保數據一致性。
- **硬件資源**:考慮硬件資源的分配,確保分表策略能夠充分利用硬件資源。

在實施分表后,可能還需要使用數據庫中間件或應用層的邏輯來管理數據的路由和查詢,以確保數據能夠正確地分布在不同的表中。


本篇文章主要講一下水平分表方案

水平分表時,我們需要選一個字段作為分表主鍵。這種情況下用數據庫的自增id肯定不合適了,我們可以使用UUID,或者雪花算法id。

這里我們使用雪花算法生成的id.

在MySQL數據庫中,使用雪花算法(Snowflake)作為分表鍵時,確實存在一些潛在的問題,尤其是在低并發(fā)的情況下。雪花算法生成的ID是趨勢遞增的,但在低并發(fā)環(huán)境下,由于每次請求的時間戳可能不同,導致生成的ID序列在分表時可能會集中在某些表中,從而造成數據分布不均勻,這種現象稱為數據傾斜。

為什么會發(fā)生數據傾斜呢?

這是雪花id的組成

| 符號位 | 時間戳 | 工作機器ID | 序列號 |
|--------|--------|------------|---------|
| 0      | 41位    | 10位       | 12位    |

而256張表,二進制位100000000。只有9位

雪花id和256進行與運算或者模運算的時候真正參與運算的只有9位

那么也就是雪花id序列號的部分,那么低并發(fā)下,序列號可能一直是一個值或者幾個值例如000000000001

000000000001
AND 0000000100000000
-------------------
000000000001

那么這樣的情況下就會導致table_1的表存儲了大量的數據,而table_2,3,4,5,6......256分不到數據。?

說到數據傾斜,我們需要了解基本的位運算(與、或、非、模)

與(AND)、或(OR)、非(NOT)、模(Modulo)這四種位運算都可以用來確定一個范圍內的值,但它們適用的場景和實現方式有所不同。以下是每種運算符如何用于確定一個特定范圍內的值:

1. **模運算(Modulo)**:
? ?模運算是最直接的方式來將一個數值映射到一個給定的范圍。例如,如果你有一個很大的數值,你想將其映射到1-256的范圍,你可以使用模運算:
? ?```java
? ?int value = someLargeNumber % 256;
? ?// value 現在是0-255,加1使其變?yōu)?-256
? ?int rangeValue = value + 1;
? ?```

2. **與運算(Bitwise AND)**:
? ?與運算可以用來提取數值的特定位。如果你想要限制數值在一個范圍內,你可以使用與運算來獲取數值的低位:
? ?```java
? ?int value = someNumber & (256 - 1); // 256 - 1 是0xFF,即11111111二進制
? ?// value 現在是0-255
? ?int rangeValue = value + 1; // 使其變?yōu)?-256
? ?```

3. **或運算(Bitwise OR)**:
? ?或運算通常用于設置特定位,而不是限制數值范圍。不過,你可以結合其他運算來使用或運算。例如,你可以先將數值與一個掩碼進行與運算,然后與一個值進行或運算來設置高位:
? ?```java
? ?int value = (someNumber & (256 - 1)) | 0x100; // 將高位設置為1
? ?// value 現在是256-511,但通常我們不需要這樣來確定范圍值
? ?```

4. **非運算(Bitwise NOT)**:
? ?非運算用于反轉位,它本身不直接用于確定一個范圍內的值。但是,它可以與其他位運算結合使用來實現復雜的位操作:
? ?```java
? ?int value = ~someNumber & (256 - 1);
? ?// 這將反轉someNumber的位,然后限制在0-255范圍內
? ?int rangeValue = value + 1; // 使其變?yōu)?-256
? ?```

在實際應用中,模運算是最常用于將數值映射到特定范圍的方法。與運算也可以實現類似的功能,特別是當你想要保留數值的低位時?;蜻\算和非運算通常用于其他類型的位操作,而不是直接用于范圍限制,但它們可以與其他運算結合使用來實現復雜的邏輯。

選擇哪種運算取決于你的具體需求,例如數據的當前范圍、目標范圍、以及你是否需要保留數值的某些位。在設計分表策略時,通常會根據數據分布的均勻性和系統(tǒng)的擴展性來選擇合適的方法。
?


在數據庫分表和分庫的場景中,除了基本的位運算(與、或、非、模),以下是一些額外的概念和知識點,它們對于設計和實現高效的分片策略非常重要:

1. **一致性哈希(Consistent Hashing)**:
? ?一致性哈希是一種特殊的哈希算法,用于分布式系統(tǒng)中,可以在節(jié)點(如數據庫分片)增加或刪除時最小化數據遷移。它通過將數據映射到一個環(huán)狀空間來實現。

2. **虛擬節(jié)點(Virtual Nodes)**:
? ?在一致性哈希中,為了解決節(jié)點分布不均勻的問題,通常會引入虛擬節(jié)點。每個物理節(jié)點可以對應多個虛擬節(jié)點,這些節(jié)點均勻分布在哈希環(huán)上。

3. **數據傾斜(Data Skew)**:
? ?數據傾斜是指數據在不同的分片之間分布不均勻,導致某些分片負載過高,而其他分片則相對空閑。需要采取措施來避免或減輕數據傾斜。

4. **范圍分片(Range Sharding)**:
? ?根據數據的某個連續(xù)范圍(如時間戳、ID范圍)來分配到不同的分片。這種方法簡單直觀,但可能會導致某些分片成為熱點。

5. **列表分片(List Sharding)**:
? ?根據數據的某個離散值(如國家代碼、用戶類型)來分配到不同的分片。這種方法適用于值域較小且分布均勻的場景。

6. **哈希分片(Hash Sharding)**:
? ?使用哈希函數將數據均勻分配到不同的分片。這種方法可以很好地分散負載,但需要注意選擇合適的哈希函數以避免數據傾斜。

7. **鍵分片(Key Sharding)**:
? ?根據數據的某個鍵值(如用戶ID、訂單ID)來分配到不同的分片。這種方法可以保持相關數據的局部性,便于查詢。

8. **分布式ID生成策略**:
? ?在分布式系統(tǒng)中,需要生成全局唯一的ID,常用的方法包括UUID、雪花算法(Snowflake)、遞增序列等。

9. **跨分片查詢(Cross-Shard Query)**:
? ?當查詢條件不落在單個分片的范圍內時,可能需要跨多個分片進行查詢,這會增加查詢的復雜性和成本。

10. **分布式事務管理**:
? ? 在分片的環(huán)境中,保持事務的一致性是一個挑戰(zhàn)??赡苄枰褂脙呻A段提交(2PC)、補償事務(TCC)或最終一致性模型。

11. **數據遷移策略**:
? ? 隨著業(yè)務的發(fā)展,可能需要對分片進行擴容或縮容,這涉及到數據的遷移。需要設計高效的數據遷移策略以最小化對業(yè)務的影響。

12. **元數據管理**:
? ? 在分片環(huán)境中,需要管理分片的元數據,如分片的映射關系、分片的健康狀態(tài)等。

了解這些概念和策略有助于在設計分庫分表方案時做出更合理的決策,從而提高系統(tǒng)的性能、可擴展性和穩(wěn)定性。
?


雪花算法為了避免數據傾斜,導致部分數據全部存儲到幾張表中。

隨機化序列號:在低并發(fā)情況下,可以通過在算法中引入隨機化序列號來使ID分布更加均勻。例如,美團的Leaf分布式ID生成服務就采用了這種方法,通過在每個毫秒內為序列號添加一個隨機偏移量來實現ID的隨機化分布。

美團的代碼https://github.com/Meituan-Dianping/Leaf/blob/master/leaf-core/src/main/java/com/sankuai/inf/leaf/snowflake/SnowflakeIDGenImpl.java

package com.sankuai.inf.leaf;import com.sankuai.inf.leaf.common.Result;public interface IDGen {Result get(String key);boolean init();
}
package com.sankuai.inf.leaf.snowflake;import com.google.common.base.Preconditions;
import com.sankuai.inf.leaf.IDGen;
import com.sankuai.inf.leaf.common.Result;
import com.sankuai.inf.leaf.common.Status;
import com.sankuai.inf.leaf.common.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.Random;public class SnowflakeIDGenImpl implements IDGen {@Overridepublic boolean init() {return true;}private static final Logger LOGGER = LoggerFactory.getLogger(SnowflakeIDGenImpl.class);private final long twepoch;private final long workerIdBits = 10L;private final long maxWorkerId = ~(-1L << workerIdBits);//最大能夠分配的workerid =1023private final long sequenceBits = 12L;private final long workerIdShift = sequenceBits;private final long timestampLeftShift = sequenceBits + workerIdBits;private final long sequenceMask = ~(-1L << sequenceBits);private long workerId;private long sequence = 0L;private long lastTimestamp = -1L;private static final Random RANDOM = new Random();public SnowflakeIDGenImpl(String zkAddress, int port) {//Thu Nov 04 2010 09:42:54 GMT+0800 (中國標準時間) this(zkAddress, port, 1288834974657L);}/*** @param zkAddress zk地址* @param port      snowflake監(jiān)聽端口* @param twepoch   起始的時間戳*/public SnowflakeIDGenImpl(String zkAddress, int port, long twepoch) {this.twepoch = twepoch;Preconditions.checkArgument(timeGen() > twepoch, "Snowflake not support twepoch gt currentTime");final String ip = Utils.getIp();SnowflakeZookeeperHolder holder = new SnowflakeZookeeperHolder(ip, String.valueOf(port), zkAddress);LOGGER.info("twepoch:{} ,ip:{} ,zkAddress:{} port:{}", twepoch, ip, zkAddress, port);boolean initFlag = holder.init();if (initFlag) {workerId = holder.getWorkerID();LOGGER.info("START SUCCESS USE ZK WORKERID-{}", workerId);} else {Preconditions.checkArgument(initFlag, "Snowflake Id Gen is not init ok");}Preconditions.checkArgument(workerId >= 0 && workerId <= maxWorkerId, "workerID must gte 0 and lte 1023");}@Overridepublic synchronized Result get(String key) {long timestamp = timeGen();if (timestamp < lastTimestamp) {long offset = lastTimestamp - timestamp;if (offset <= 5) {try {wait(offset << 1);timestamp = timeGen();if (timestamp < lastTimestamp) {return new Result(-1, Status.EXCEPTION);}} catch (InterruptedException e) {LOGGER.error("wait interrupted");return new Result(-2, Status.EXCEPTION);}} else {return new Result(-3, Status.EXCEPTION);}}if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {//seq 為0的時候表示是下一毫秒時間開始對seq做隨機sequence = RANDOM.nextInt(100);timestamp = tilNextMillis(lastTimestamp);}} else {//如果是新的ms開始sequence = RANDOM.nextInt(100);}lastTimestamp = timestamp;long id = ((timestamp - twepoch) << timestampLeftShift) | (workerId << workerIdShift) | sequence;return new Result(id, Status.SUCCESS);}protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}protected long timeGen() {return System.currentTimeMillis();}public long getWorkerId() {return workerId;}}

?sequence = RANDOM.nextInt(100);

就是對每毫秒起始的sequence取隨值,美團的隨機范圍是0到100。最終的效果就是生成的id會均勻分布在tb_0到tb_100。而我們如果分表數是256,則需要改成

sequence = RANDOM.nextInt(256);

或者用下面這個簡化版本

import java.util.concurrent.ThreadLocalRandom;public class RandomizedSnowflakeIdWorker {private long lastTimestamp = -1L;private long sequence = 0L;private final long workerIdBits = 5L;private final long datacenterIdBits = 5L;private final long maxWorkerId = -1L ^ (-1L << workerIdBits);private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);private final long sequenceBits = 12L;private final long workerIdShift = sequenceBits;private final long datacenterIdShift = sequenceBits + workerIdBits;private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private final long sequenceMask = -1L ^ (-1L << sequenceBits);private final long twepoch = 1288834974657L;private long workerId;private long datacenterId;public RandomizedSnowflakeIdWorker(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {sequence = ThreadLocalRandom.current().nextLong(sequenceMask + 1);}lastTimestamp = timestamp;return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;}protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}protected long timeGen() {return System.currentTimeMillis();}public static void main(String[] args) {RandomizedSnowflakeIdWorker idWorker = new RandomizedSnowflakeIdWorker(0, 0);for (int i = 0; i < 1000; i++) {long id = idWorker.nextId();System.out.println(Long.toBinaryString(id));System.out.println(id);}}
}

在這個示例中,sequence 在每次調用 nextId 方法時都會隨機化,而不是自增。這是通過 ThreadLocalRandom.current().nextLong(sequenceMask + 1) 實現的,它會在每個毫秒內生成一個隨機的序列號。這樣可以確保在高并發(fā)情況下,生成的ID更加分散,減少數據傾斜的風險。

請注意,這個示例是一個簡化的版本,實際應用中可能需要更復雜的邏輯來確保ID的全局唯一性和趨勢遞增性。此外,時鐘回撥的處理也需要根據實際需求進行設計。

雪花id+hash散列表

int tableIndex = (int)(snowflakeId.hashCode() & 0xFFFFFFFF) % 256;


關于雪花id時鐘回撥的問題有一下幾個解決方案

雪花算法(Snowflake)是一種廣泛使用的分布式唯一ID生成方法,它通過結合時間戳、機器ID和序列號來生成一個64位的長整型ID。這種算法能夠確保在分布式系統(tǒng)中生成全局唯一的ID,并且具有高性能和高可用性的特點。

然而,雪花算法的一個潛在問題是時鐘回撥,即服務器時間意外地回退到之前的時間。這可能導致生成重復的ID,因為算法依賴于時間戳來保證ID的唯一性。以下是幾種解決時鐘回撥問題的策略:

1. **直接拋出異常**:
? ?如果檢測到時鐘回撥,算法可以拒絕生成新的ID并直接拋出異常。這是一種簡單直接的方法,但可能會導致服務中斷。

2. **等待策略**:
? ?當檢測到時鐘回撥時,服務可以等待直到系統(tǒng)時鐘恢復到正常狀態(tài)。這種方法可以確保ID的嚴格遞增性,但可能會在時鐘調整期間暫停服務。

3. **序列號持久化**:
? ?將序列號持久化存儲(例如在數據庫中),這樣即使發(fā)生時鐘回撥,也可以從持久化存儲中恢復最后一個序列號,從而繼續(xù)生成新的ID。

4. **使用歷史時間戳**:
? ?在某些實現中,可以使用一個“歷史時間戳”來代替當前時間戳,每次請求只增加序列號,當序列號用完時,再增加歷史時間戳。

5. **增加容忍時鐘回撥的時間閾值**:
? ?在算法中設置一個容忍時鐘回撥的時間閾值,如果回撥時間在這個閾值內,算法可以等待或采取其他措施,而不是立即拋出異常。

6. **備用機方案**:
? ?如果當前機器出現時鐘回撥,可以嘗試切換到備用機器上繼續(xù)提供服務。

7. **采用之前最大時間**:
? ?當檢測到時鐘回撥時,可以采用之前記錄的最大時間戳和序列號繼續(xù)生成ID。

8. **基于時鐘序列的方案**:
? ?將機器ID拆分為時鐘序列和機器碼,發(fā)生時間回撥時,增加時鐘序列的值,從而生成新的ID。

這些策略可以單獨使用,也可以組合使用,以提供更強的容錯能力和更高的可用性。在實際應用中,應根據業(yè)務需求和系統(tǒng)特性選擇最合適的解決方案。
?


在分布式系統(tǒng)中,確保時鐘同步的準確無誤是至關重要的,因為時間的一致性對于事件的順序、數據的一致性和系統(tǒng)的協(xié)調運行都有著直接的影響。以下是一些確保分布式系統(tǒng)中時鐘同步準確無誤的策略:

1. **使用網絡時間協(xié)議(NTP)**:NTP 是一種廣泛使用的時鐘同步協(xié)議,它允許分布式系統(tǒng)中的每個節(jié)點與一個或多個時間服務器進行通信,以同步其時鐘。NTP 通過逐步逼近的方式來減少時差,確保了整個系統(tǒng)內各個節(jié)點的時鐘同步。

2. **配置NTP服務器**:在分布式集群中,可以設置一個或多個服務器作為NTP服務器,其他節(jié)點則作為客戶端定期從這些服務器同步時間。如果集群中的所有節(jié)點都能訪問互聯(lián)網,可以直接與公共NTP服務器同步。如果只有部分節(jié)點可以訪問互聯(lián)網,可以選擇其中一個作為時間服務器,其他節(jié)點從這個時間服務器同步時間。

3. **手動時間同步**:在某些情況下,如果集群中的節(jié)點無法訪問互聯(lián)網,可能需要手動設置服務器節(jié)點的時間,并定期進行校準。

4. **使用精確時間協(xié)議(PTP)**:在需要更高時間精度的場合,可以使用PTP。PTP通過主從架構在主時鐘和從時鐘之間交換同步信息,利用特殊的時間戳和硬件支持來減少測量延遲,實現高精度同步。

5. **向量時鐘和邏輯時鐘**:向量時鐘和邏輯時鐘是解決分布式系統(tǒng)中時鐘同步問題的軟件方案。它們通過為每個事件分配一個時間戳來記錄事件的因果關系,從而在沒有物理時鐘同步的情況下保持事件的一致性順序。

6. **TrueTime和混合邏輯時鐘(HLC)**:TrueTime是Google提出的概念,用于在分布式系統(tǒng)中提高物理時鐘的可靠性。HLC結合了邏輯時鐘和物理時鐘的優(yōu)點,支持對事件進行因果關系排序,同時又有物理時鐘直觀的特點。

7. **監(jiān)控和告警**:對系統(tǒng)時鐘進行監(jiān)控,并在檢測到時鐘回撥或偏差超過閾值時觸發(fā)告警,以便運維人員可以及時發(fā)現問題并進行處理。

8. **優(yōu)化ID生成算法**:除了引入容忍時鐘回撥的閾值外,還可以根據實際需求對ID生成算法進行優(yōu)化,以提高ID生成速度和唯一性。

通過上述方法,可以有效地確保分布式系統(tǒng)中的時鐘同步,從而保障系統(tǒng)的穩(wěn)定運行和數據一致性。
?

http://m.risenshineclean.com/news/41225.html

相關文章:

  • 廣西做網站的公司有哪些谷歌關鍵詞工具
  • 網站建設系統(tǒng)哪家便宜些seo廣告平臺
  • 手表到哪個網站買新網站應該怎么做seo
  • 天河做網站哪家好沒干過網絡推廣能干嗎
  • 通遼做網站制作公司一個公司可以做幾個百度推廣
  • 網購app有哪些?長沙seo計費管理
  • 網站設計的總結深圳網站快速排名優(yōu)化
  • 免費建站網站大全長沙網站推廣seo
  • 網站建設后臺是什么推廣聯(lián)盟平臺
  • 購物網站開發(fā)實戰(zhàn)企業(yè)網站優(yōu)化排名
  • 做國際貿易都用什么網站seo優(yōu)化排名是什么
  • 網站建設驗收標準銷售推廣方案
  • 烏魯木齊培訓網站建設網站自然優(yōu)化
  • 黃驊市第三中學關鍵詞優(yōu)化包年推廣
  • 如何寫一個可以做報價計算的網站網絡服務網絡推廣
  • 為什么自己做的網站別的電腦打不開廣州新聞最新消息今天
  • 怎么做游戲自動充值的網站重慶高端網站seo
  • 信息化平臺的功能介紹搜索引擎優(yōu)化 簡歷
  • 深圳住房和建設局網站輪候大廳網絡營銷屬于什么專業(yè)類型
  • 移動端使用wordpress富文本編輯器便宜的seo官網優(yōu)化
  • 全自動網站建設最新實時大數據
  • wordpress好用還是dede磐石網站seo
  • 上海高端定制網站公司關鍵詞優(yōu)化的技巧
  • 門戶網登錄入口seo軟件定制
  • wordpress視覺編輯器seo在線優(yōu)化工具
  • 上海網站公司電話seo推廣是什么意思
  • 權大師的網站是哪個公司做的香港疫情最新消息
  • 網站建設為中心百度關鍵詞收錄
  • 個人主頁自助建站搜索引擎的工作原理分為
  • 孝感 網站建設百度電商廣告代運營